2018-09-25 23:45:43 -04:00
# frozen_string_literal: true
2012-09-17 10:08:02 -04:00
# Controller for a specific Commit
#
# Not to be confused with CommitsController, plural.
2013-06-23 12:47:22 -04:00
class Projects :: CommitController < Projects :: ApplicationController
2017-03-30 23:06:09 -04:00
include RendersNotes
2016-02-03 16:11:59 -05:00
include CreatesCommit
2016-07-06 13:15:27 -04:00
include DiffForPath
2016-03-03 12:38:44 -05:00
include DiffHelper
2020-01-08 01:08:13 -05:00
include SourcegraphDecorator
2016-02-03 16:11:59 -05:00
2012-09-17 10:08:02 -04:00
# Authorize
2015-04-16 08:03:37 -04:00
before_action :require_non_empty_project
2016-11-29 08:02:28 -05:00
before_action :authorize_download_code!
2016-09-13 07:44:01 -04:00
before_action :authorize_read_pipeline! , only : [ :pipelines ]
2015-04-16 08:03:37 -04:00
before_action :commit
2020-08-12 08:10:25 -04:00
before_action :define_commit_vars , only : [ :show , :diff_for_path , :diff_files , :pipelines , :merge_requests ]
2021-03-15 14:09:05 -04:00
before_action :define_commit_box_vars , only : [ :show , :pipelines ]
2020-08-12 08:10:25 -04:00
before_action :define_note_vars , only : [ :show , :diff_for_path , :diff_files ]
2016-04-18 03:39:07 -04:00
before_action :authorize_edit_tree! , only : [ :revert , :cherry_pick ]
2021-03-15 17:09:16 -04:00
2017-10-13 13:11:11 -04:00
BRANCH_SEARCH_LIMIT = 1000
2021-04-20 17:09:07 -04:00
COMMIT_DIFFS_PER_PAGE = 20
2017-10-13 13:11:11 -04:00
2020-10-08 14:08:32 -04:00
feature_category :source_code_management
2021-11-12 13:12:20 -05:00
urgency :low , [ :pipelines , :merge_requests , :show ]
2020-10-08 14:08:32 -04:00
2012-09-17 10:08:02 -04:00
def show
2015-10-22 21:52:17 -04:00
apply_diff_view_cookie!
2012-09-25 18:46:19 -04:00
respond_to do | format |
2019-01-16 07:09:29 -05:00
format . html do
2022-04-11 11:09:47 -04:00
render locals : { pagination_params : params . permit ( :page ) }
2018-07-16 12:18:52 -04:00
end
2019-01-16 07:09:29 -05:00
format . diff do
2018-05-15 11:05:19 -04:00
send_git_diff ( @project . repository , @commit . diff_refs )
end
format . patch do
send_git_patch ( @project . repository , @commit . diff_refs )
end
2012-09-17 10:08:02 -04:00
end
end
2014-01-15 08:06:12 -05:00
2016-06-28 12:25:32 -04:00
def diff_for_path
2016-07-27 13:00:34 -04:00
render_diff_for_path ( @commit . diffs ( diff_options ) )
2016-06-28 12:25:32 -04:00
end
2020-08-12 08:10:25 -04:00
def diff_files
2021-04-20 11:09:24 -04:00
render template : 'projects/commit/diff_files' , layout : false , locals : { diffs : @diffs , environment : @environment }
2020-08-12 08:10:25 -04:00
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2016-09-13 07:44:01 -04:00
def pipelines
2017-01-27 07:32:21 -05:00
@pipelines = @commit . pipelines . order ( id : :desc )
2021-06-30 14:07:05 -04:00
@pipelines = @pipelines . where ( ref : params [ :ref ] ) if params [ :ref ]
@pipelines = @pipelines . page ( params [ :page ] )
2017-01-27 07:32:21 -05:00
respond_to do | format |
format . html
format . json do
2017-04-05 10:36:14 -04:00
Gitlab :: PollingInterval . set_header ( response , interval : 10_000 )
2017-07-14 11:52:54 -04:00
render json : {
pipelines : PipelineSerializer
. new ( project : @project , current_user : @current_user )
2018-10-30 11:56:30 -04:00
. with_pagination ( request , response )
2017-07-14 11:52:54 -04:00
. represent ( @pipelines ) ,
count : {
all : @pipelines . count
}
}
2017-01-27 07:32:21 -05:00
end
end
2016-09-13 07:44:01 -04:00
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2016-09-13 07:44:01 -04:00
2018-01-12 15:38:36 -05:00
def merge_requests
2019-01-25 04:22:48 -05:00
@merge_requests = MergeRequestsFinder . new (
current_user ,
project_id : @project . id ,
commit_sha : @commit . sha
) . execute . map do | mr |
2018-01-12 15:38:36 -05:00
{ iid : mr . iid , path : merge_request_path ( mr ) , title : mr . title }
end
respond_to do | format |
format . json do
render json : @merge_requests . to_json
end
end
end
2015-02-03 00:30:11 -05:00
def branches
2022-02-01 10:18:50 -05:00
return git_not_found! unless commit
2017-10-12 09:31:43 -04:00
# branch_names_contains/tag_names_contains can take a long time when there are thousands of
# branches/tags - each `git branch --contains xxx` request can consume a cpu core.
# so only do the query when there are a manageable number of branches/tags
2017-10-13 13:11:11 -04:00
@branches_limit_exceeded = @project . repository . branch_count > BRANCH_SEARCH_LIMIT
@branches = @branches_limit_exceeded ? [ ] : @project . repository . branch_names_contains ( commit . id )
@tags_limit_exceeded = @project . repository . tag_count > BRANCH_SEARCH_LIMIT
@tags = @tags_limit_exceeded ? [ ] : @project . repository . tag_names_contains ( commit . id )
2015-02-03 00:30:11 -05:00
render layout : false
end
2016-02-03 16:11:59 -05:00
def revert
2022-03-20 23:08:23 -04:00
return render_404 unless @commit
2017-01-05 13:11:27 -05:00
assign_change_commit_vars
2016-02-18 11:58:04 -05:00
2017-02-16 19:24:56 -05:00
return render_404 if @start_branch . blank?
2017-04-19 20:37:44 -04:00
@branch_name = create_new_branch? ? @commit . revert_branch_name : @start_branch
2016-02-03 16:11:59 -05:00
2016-11-29 08:47:43 -05:00
create_commit ( Commits :: RevertService , success_notice : " The #{ @commit . change_type_title ( current_user ) } has been successfully reverted. " ,
2021-04-12 17:11:12 -04:00
success_path : - > { successful_change_path ( @project ) } , failure_path : failed_change_path )
2016-02-03 16:11:59 -05:00
end
2016-05-10 18:41:46 -04:00
2016-04-18 03:39:07 -04:00
def cherry_pick
2022-03-20 23:08:23 -04:00
return render_404 unless @commit
2017-01-05 13:11:27 -05:00
assign_change_commit_vars
2016-05-10 18:41:46 -04:00
2017-02-16 19:24:56 -05:00
return render_404 if @start_branch . blank?
2021-04-12 17:11:12 -04:00
target_project = find_cherry_pick_target_project
return render_404 unless target_project
2017-04-19 20:37:44 -04:00
@branch_name = create_new_branch? ? @commit . cherry_pick_branch_name : @start_branch
2016-02-03 16:11:59 -05:00
2018-08-19 16:28:54 -04:00
create_commit ( Commits :: CherryPickService , success_notice : " The #{ @commit . change_type_title ( current_user ) } has been successfully cherry-picked into #{ @branch_name } . " ,
2021-04-12 17:11:12 -04:00
success_path : - > { successful_change_path ( target_project ) } ,
failure_path : failed_change_path ,
target_project : target_project )
2016-02-08 15:37:27 -05:00
end
2016-04-18 03:39:07 -04:00
private
2017-02-16 19:24:56 -05:00
def create_new_branch?
params [ :create_merge_request ] . present? || ! can? ( current_user , :push_code , @project )
end
2021-04-12 17:11:12 -04:00
def successful_change_path ( target_project )
referenced_merge_request_url || project_commits_url ( target_project , @branch_name )
2016-02-08 15:37:27 -05:00
end
2016-04-18 03:39:07 -04:00
def failed_change_path
2017-06-29 13:06:35 -04:00
referenced_merge_request_url || project_commit_url ( @project , params [ :id ] )
2016-02-08 15:37:27 -05:00
end
def referenced_merge_request_url
2016-11-29 08:47:43 -05:00
if merge_request = @commit . merged_merge_request ( current_user )
2017-06-29 13:06:35 -04:00
project_merge_request_url ( merge_request . target_project , merge_request )
2016-11-29 08:47:43 -05:00
end
2016-02-08 15:37:27 -05:00
end
2014-01-15 08:06:12 -05:00
def commit
2018-07-16 12:18:52 -04:00
@noteable = @commit || = @project . commit_by ( oid : params [ :id ] ) . tap do | commit |
# preload author and their status for rendering
commit & . author & . status
end
2014-01-15 08:06:12 -05:00
end
2015-10-23 05:41:22 -04:00
2016-07-06 13:15:27 -04:00
def define_commit_vars
2016-02-15 15:48:16 -05:00
return git_not_found! unless commit
2016-03-03 12:38:44 -05:00
opts = diff_options
opts [ :ignore_whitespace_change ] = true if params [ :format ] == 'diff'
2022-02-22 10:18:06 -05:00
opts [ :use_extra_viewer_as_main ] = false
2015-11-30 04:30:44 -05:00
2016-07-27 13:00:34 -04:00
@diffs = commit . diffs ( opts )
2015-11-03 05:44:07 -05:00
@notes_count = commit . notes . count
2017-02-16 19:24:56 -05:00
2021-04-22 11:09:56 -04:00
@environment = :: Environments :: EnvironmentsByDeploymentsFinder . new ( @project , current_user , commit : @commit , find_latest : true ) . execute . last
2016-07-06 13:15:27 -04:00
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2016-07-06 13:15:27 -04:00
def define_note_vars
2017-03-09 20:29:11 -05:00
@noteable = @commit
2016-07-06 13:15:27 -04:00
@note = @project . build_commit_note ( commit )
2017-03-09 20:29:11 -05:00
@new_diff_note_attrs = {
2016-07-06 13:15:27 -04:00
noteable_type : 'Commit' ,
commit_id : @commit . id
}
2017-03-09 20:29:11 -05:00
@grouped_diff_discussions = commit . grouped_diff_discussions
@discussions = commit . discussions
2017-06-29 17:19:09 -04:00
if merge_request_iid = params [ :merge_request_iid ]
@merge_request = MergeRequestsFinder . new ( current_user , project_id : @project . id ) . find_by ( iid : merge_request_iid )
if @merge_request
@new_diff_note_attrs . merge! (
noteable_type : 'MergeRequest' ,
noteable_id : @merge_request . id
)
merge_request_commit_notes = @merge_request . notes . where ( commit_id : @commit . id ) . inc_relations_for_view
merge_request_commit_diff_discussions = merge_request_commit_notes . grouped_diff_discussions ( @commit . diff_refs )
@grouped_diff_discussions . merge! ( merge_request_commit_diff_discussions ) do | line_code , left , right |
left + right
end
end
end
2017-03-30 22:34:14 -04:00
@notes = ( @grouped_diff_discussions . values . flatten + @discussions ) . flat_map ( & :notes )
2017-07-29 11:04:42 -04:00
@notes = prepare_notes_for_rendering ( @notes , @commit )
2016-07-06 13:15:27 -04:00
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2015-12-08 07:03:28 -05:00
2021-03-15 14:09:05 -04:00
def define_commit_box_vars
@last_pipeline = @commit . last_pipeline
return unless @commit . last_pipeline
@last_pipeline_stages = StageSerializer . new ( project : @project , current_user : @current_user ) . represent ( @last_pipeline . stages )
end
2017-01-05 13:11:27 -05:00
def assign_change_commit_vars
2017-02-16 19:24:56 -05:00
@start_branch = params [ :start_branch ]
@commit_params = { commit : @commit }
2016-02-03 18:28:40 -05:00
end
2021-04-12 17:11:12 -04:00
def find_cherry_pick_target_project
return @project if params [ :target_project_id ] . blank?
MergeRequestTargetProjectFinder
. new ( current_user : current_user , source_project : @project , project_feature : :repository )
. execute
. find_by_id ( params [ :target_project_id ] )
end
2012-09-17 10:08:02 -04:00
end