2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
module MergeRequestsHelper
2020-01-01 13:55:28 +05:30
include Gitlab :: Utils :: StrongMemoize
2023-05-27 22:25:52 +05:30
include CompareHelper
2020-01-01 13:55:28 +05:30
2022-08-27 11:52:29 +05:30
def create_mr_button_from_event? ( event )
create_mr_button? ( from : event . branch_name , source_project : event . project )
2014-09-02 18:07:02 +05:30
end
2022-08-27 11:52:29 +05:30
def create_mr_path_from_push_event ( event )
create_mr_path ( from : event . branch_name , source_project : event . project )
2014-09-02 18:07:02 +05:30
end
2015-04-26 12:48:37 +05:30
def mr_css_classes ( mr )
2018-12-05 23:21:45 +05:30
classes = [ " merge-request " ]
classes << " closed " if mr . closed?
classes << " merged " if mr . merged?
classes . join ( ' ' )
2014-09-02 18:07:02 +05:30
end
2022-08-27 11:52:29 +05:30
def merge_path_description ( merge_request , with_arrow : false )
2014-09-02 18:07:02 +05:30
if merge_request . for_fork?
2022-08-27 11:52:29 +05:30
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
}
2014-09-02 18:07:02 +05:30
else
2022-08-27 11:52:29 +05:30
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
}
2014-09-02 18:07:02 +05:30
end
end
2015-09-11 14:41:01 +05:30
def mr_change_branches_path ( merge_request )
2017-09-10 17:25:29 +05:30
project_new_merge_request_path (
@project ,
2015-09-11 14:41:01 +05:30
merge_request : {
2017-08-17 22:00:37 +05:30
source_project_id : merge_request . source_project_id ,
target_project_id : merge_request . target_project_id ,
source_branch : merge_request . source_branch ,
2017-09-10 17:25:29 +05:30
target_branch : merge_request . target_branch
2015-12-23 02:04:40 +05:30
} ,
change_branches : true
2015-09-11 14:41:01 +05:30
)
end
2015-10-24 18:46:33 +05:30
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
2016-08-24 12:49:21 +05:30
2017-08-17 22:00:37 +05:30
def target_projects ( project )
2018-03-17 18:26:18 +05:30
MergeRequestTargetProjectFinder . new ( current_user : current_user , source_project : project )
2020-01-01 13:55:28 +05:30
. execute ( include_routes : true )
2017-08-17 22:00:37 +05:30
end
2016-08-24 12:49:21 +05:30
def merge_request_button_visibility ( merge_request , closed )
2018-12-05 23:21:45 +05:30
return 'hidden' if merge_request_button_hidden? ( merge_request , closed )
end
def merge_request_button_hidden? ( merge_request , closed )
2021-02-22 17:27:13 +05:30
merge_request . closed? == closed || ( merge_request . merged? == closed && ! merge_request . closed? ) || merge_request . closed_or_merged_without_fork?
2016-09-29 09:46:39 +05:30
end
def merge_request_version_path ( project , merge_request , merge_request_diff , start_sha = nil )
2017-09-10 17:25:29 +05:30
diffs_project_merge_request_path ( project , merge_request , diff_id : merge_request_diff . id , start_sha : start_sha )
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
def merge_params ( merge_request )
{
2019-09-04 21:01:54 +05:30
auto_merge_strategy : AutoMergeService :: STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS ,
2017-08-17 22:00:37 +05:30
should_remove_source_branch : true ,
2018-11-08 19:23:39 +05:30
sha : merge_request . diff_head_sha ,
2020-07-28 23:09:34 +05:30
squash : merge_request . squash_on_merge?
2018-11-08 19:23:39 +05:30
}
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
def tab_link_for ( merge_request , tab , options = { } , & block )
data_attrs = {
action : tab . to_s ,
target : " # #{ tab } " ,
2018-11-08 19:23:39 +05:30
toggle : options . fetch ( :force_link , false ) ? '' : 'tabvue'
2018-03-17 18:26:18 +05:30
}
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 )
else
raise " Cannot create tab #{ tab } . "
end
link_to ( url [ merge_request . project , merge_request ] , data : data_attrs , & block )
end
2018-11-08 19:23:39 +05:30
def allow_collaboration_unavailable_reason ( merge_request )
return if merge_request . can_allow_collaboration? ( current_user )
2018-03-27 19:54:05 +05:30
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' )
end
end
2018-05-09 12:01:36 +05:30
def merge_request_source_project_for_project ( project = @project )
unless can? ( current_user , :create_merge_request_in , project )
2019-07-07 11:18:12 +05:30
return
2018-05-09 12:01:36 +05:30
end
if can? ( current_user , :create_merge_request_from , project )
project
else
current_user . fork_of ( project )
end
end
2021-02-22 17:27:13 +05:30
def toggle_draft_merge_request_path ( issuable )
2022-07-23 23:45:48 +05:30
wip_event = issuable . draft? ? 'ready' : 'draft'
2021-02-22 17:27:13 +05:30
issuable_path ( issuable , { merge_request : { wip_event : wip_event } } )
end
2021-03-08 18:12:59 +05:30
def user_merge_requests_counts
@user_merge_requests_counts || = begin
assigned_count = assigned_issuables_count ( :merge_requests )
review_requested_count = review_requested_merge_requests_count
total_count = assigned_count + review_requested_count
2022-08-27 11:52:29 +05:30
{
2021-03-08 18:12:59 +05:30
assigned : assigned_count ,
review_requested : review_requested_count ,
total : total_count
}
end
end
2021-04-17 20:07:23 +05:30
def reviewers_label ( merge_request , include_value : true )
reviewers = merge_request . reviewers
if include_value
sanitized_list = sanitize_name ( reviewers . map ( & :name ) . to_sentence )
2021-04-29 21:17:54 +05:30
ns_ ( 'NotificationEmail|Reviewer: %{users}' , 'NotificationEmail|Reviewers: %{users}' , reviewers . count ) % { users : sanitized_list }
2021-04-17 20:07:23 +05:30
else
2021-04-29 21:17:54 +05:30
ns_ ( 'NotificationEmail|Reviewer' , 'NotificationEmail|Reviewers' , reviewers . count )
end
end
2023-07-09 08:55:56 +05:30
def moved_mr_sidebar_enabled?
Feature . enabled? ( :moved_mr_sidebar , @project )
end
2021-04-29 21:17:54 +05:30
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_metadata_url ,
endpoint_batch : diffs_batch_project_json_merge_request_path ( project , merge_request , 'json' , params ) ,
endpoint_coverage : @coverage_path ,
2023-06-20 00:43:36 +05:30
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 ) ,
2022-06-21 17:19:12 +05:30
help_page_path : help_page_path ( 'user/project/merge_requests/reviews/suggestions.md' ) ,
2021-04-29 21:17:54 +05:30
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/merge_request_changes_empty.svg' ) ,
is_fluid_layout : fluid_layout . to_s ,
2022-01-26 12:08:38 +05:30
dismiss_endpoint : callouts_path ,
2021-04-29 21:17:54 +05:30
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 ,
2023-07-09 08:55:56 +05:30
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 ,
2023-06-20 00:43:36 +05:30
new_comment_template_path : profile_comment_templates_path
2021-04-29 21:17:54 +05:30
}
end
def award_emoji_merge_request_api_path ( merge_request )
2022-06-21 17:19:12 +05:30
api_v4_projects_merge_requests_award_emoji_path ( id : merge_request . project . id , merge_request_iid : merge_request . iid )
2021-04-17 20:07:23 +05:30
end
2022-07-16 23:28:13 +05:30
def how_merge_modal_data ( merge_request )
{
is_fork : merge_request . for_fork? . to_s ,
can_merge : merge_request . can_be_merged_by? ( current_user ) . 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 ) ,
target_branch : merge_request . target_branch ,
reviewing_docs_path : help_page_path ( 'user/project/merge_requests/reviews/index.md' , anchor : " checkout-merge-requests-locally-through-the-head-ref " )
}
end
2021-03-08 18:12:59 +05:30
private
def review_requested_merge_requests_count
current_user . review_requested_open_merge_requests_count
end
2023-07-09 08:55:56 +05:30
def default_suggestion_commit_message ( project )
project . suggestion_commit_message . presence || Gitlab :: Suggestions :: CommitMessage :: DEFAULT_SUGGESTION_COMMIT_MESSAGE
2021-03-08 18:12:59 +05:30
end
2022-07-16 23:28:13 +05:30
def merge_request_source_branch ( merge_request )
2023-06-20 00:43:36 +05:30
fork_icon = if merge_request . for_fork?
title = _ ( 'The source project is a fork' )
content_tag ( :span , class : 'gl-vertical-align-middle gl-mr-n2 has-tooltip' , title : title ) do
sprite_icon ( 'fork' , size : 12 , css_class : 'gl-ml-1 has-tooltip' )
end
else
''
end
2022-07-16 23:28:13 +05:30
branch = if merge_request . for_fork?
2023-07-07 10:43:13 +05:30
html_escape ( _ ( '%{fork_icon} %{source_project_path}:%{source_branch}' ) ) % { fork_icon : fork_icon . html_safe , source_project_path : merge_request . source_project_path , source_branch : merge_request . source_branch }
2022-07-16 23:28:13 +05:30
else
merge_request . source_branch
end
2023-06-20 00:43:36 +05:30
branch_title = if merge_request . for_fork?
2023-07-07 10:43:13 +05:30
html_escape ( _ ( '%{source_project_path}:%{source_branch}' ) ) % { source_project_path : merge_request . source_project_path , source_branch : merge_request . source_branch }
2023-06-20 00:43:36 +05:30
else
merge_request . source_branch
end
2022-07-16 23:28:13 +05:30
branch_path = if merge_request . source_project
project_tree_path ( merge_request . source_project , merge_request . source_branch )
else
''
end
2023-06-20 00:43:36 +05:30
link_to branch , branch_path , title : branch_title , class : 'gl-text-blue-500! gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mx-2'
2022-07-16 23:28:13 +05:30
end
def merge_request_header ( project , merge_request )
2023-01-13 00:05:48 +05:30
link_to_author = link_to_member ( project , merge_request . author , size : 24 , extra_class : 'gl-font-weight-bold gl-mr-2' , avatar : false )
2022-07-16 23:28:13 +05:30
copy_button = clipboard_button ( text : merge_request . source_branch , title : _ ( 'Copy branch name' ) , class : 'btn btn-default btn-sm gl-button btn-default-tertiary btn-icon gl-display-none! gl-md-display-inline-block! js-source-branch-copy' )
2023-06-20 00:43:36 +05:30
2023-01-13 00:05:48 +05:30
target_branch = link_to merge_request . target_branch , project_tree_path ( merge_request . target_project , merge_request . target_branch ) , title : merge_request . target_branch , class : 'gl-text-blue-500! gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mx-2'
2022-07-16 23:28:13 +05:30
_ ( '%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}' ) . html_safe % { author : link_to_author . html_safe , source_branch : merge_request_source_branch ( merge_request ) . html_safe , copy_button : copy_button . html_safe , target_branch : target_branch . html_safe , created_at : time_ago_with_tooltip ( merge_request . created_at , html_class : 'gl-display-inline-block' ) . html_safe }
end
2023-06-20 00:43:36 +05:30
def single_file_file_by_file?
Feature . enabled? ( :single_file_file_by_file , @project )
end
2022-10-11 01:57:18 +05:30
def sticky_header_data
data = {
iid : @merge_request . iid ,
projectPath : @project . full_path ,
title : markdown_field ( @merge_request , :title ) ,
isFluidLayout : fluid_layout . 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
2023-03-17 16:20:25 +05:30
def hidden_merge_request_icon ( merge_request )
return unless merge_request . hidden?
hidden_issuable_icon ( merge_request )
end
2023-07-09 08:55:56 +05:30
def tab_count_display ( merge_request , count )
merge_request . preparing? ? " - " : count
end
2014-09-02 18:07:02 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
MergeRequestsHelper . prepend_mod_with ( 'MergeRequestsHelper' )