2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
# Controller for a specific Commit
#
# Not to be confused with CommitsController, plural.
class Projects :: CommitController < Projects :: ApplicationController
2017-08-17 22:00:37 +05:30
include RendersNotes
2016-04-02 18:10:28 +05:30
include CreatesCommit
2016-08-24 12:49:21 +05:30
include DiffForPath
2016-06-02 11:05:42 +05:30
include DiffHelper
2020-03-13 15:44:24 +05:30
include SourcegraphDecorator
2016-04-02 18:10:28 +05:30
2014-09-02 18:07:02 +05:30
# Authorize
2015-09-11 14:41:01 +05:30
before_action :require_non_empty_project
2017-08-17 22:00:37 +05:30
before_action :authorize_download_code!
2016-11-03 12:29:30 +05:30
before_action :authorize_read_pipeline! , only : [ :pipelines ]
2015-09-11 14:41:01 +05:30
before_action :commit
2020-10-24 23:57:45 +05:30
before_action :define_commit_vars , only : [ :show , :diff_for_path , :diff_files , :pipelines , :merge_requests ]
2021-04-17 20:07:23 +05:30
before_action :define_commit_box_vars , only : [ :show , :pipelines ]
2020-10-24 23:57:45 +05:30
before_action :define_note_vars , only : [ :show , :diff_for_path , :diff_files ]
2016-06-02 11:05:42 +05:30
before_action :authorize_edit_tree! , only : [ :revert , :cherry_pick ]
2014-09-02 18:07:02 +05:30
2018-03-17 18:26:18 +05:30
BRANCH_SEARCH_LIMIT = 1000
2021-06-08 01:23:25 +05:30
COMMIT_DIFFS_PER_PAGE = 20
2018-03-17 18:26:18 +05:30
2021-01-03 14:25:43 +05:30
feature_category :source_code_management
2014-09-02 18:07:02 +05:30
def show
2016-04-02 18:10:28 +05:30
apply_diff_view_cookie!
2014-09-02 18:07:02 +05:30
respond_to do | format |
2019-03-02 22:35:43 +05:30
format . html do
2018-11-18 11:00:15 +05:30
render
end
2019-03-02 22:35:43 +05:30
format . diff do
2018-11-08 19:23:39 +05:30
send_git_diff ( @project . repository , @commit . diff_refs )
end
format . patch do
send_git_patch ( @project . repository , @commit . diff_refs )
end
2014-09-02 18:07:02 +05:30
end
end
2016-08-24 12:49:21 +05:30
def diff_for_path
2016-09-13 17:45:13 +05:30
render_diff_for_path ( @commit . diffs ( diff_options ) )
2016-08-24 12:49:21 +05:30
end
2020-10-24 23:57:45 +05:30
def diff_files
2021-06-08 01:23:25 +05:30
render template : 'projects/commit/diff_files' , layout : false , locals : { diffs : @diffs , environment : @environment }
2020-10-24 23:57:45 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2016-11-03 12:29:30 +05:30
def pipelines
2017-08-17 22:00:37 +05:30
@pipelines = @commit . pipelines . order ( id : :desc )
2021-09-30 23:02:18 +05:30
@pipelines = @pipelines . where ( ref : params [ :ref ] ) if params [ :ref ]
@pipelines = @pipelines . page ( params [ :page ] )
2015-10-24 18:46:33 +05:30
2017-08-17 22:00:37 +05:30
respond_to do | format |
format . html
format . json do
Gitlab :: PollingInterval . set_header ( response , interval : 10_000 )
2015-10-24 18:46:33 +05:30
2017-09-10 17:25:29 +05:30
render json : {
pipelines : PipelineSerializer
. new ( project : @project , current_user : @current_user )
2018-12-13 13:39:08 +05:30
. with_pagination ( request , response )
2017-09-10 17:25:29 +05:30
. represent ( @pipelines ) ,
count : {
all : @pipelines . count
}
}
2015-11-26 14:37:03 +05:30
end
end
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2015-10-24 18:46:33 +05:30
2018-03-17 18:26:18 +05:30
def merge_requests
2019-03-13 22:55:13 +05:30
@merge_requests = MergeRequestsFinder . new (
current_user ,
project_id : @project . id ,
commit_sha : @commit . sha
) . execute . map do | mr |
2018-03-17 18:26:18 +05:30
{ 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-04-26 12:48:37 +05:30
def branches
2018-03-17 18:26:18 +05:30
# 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
@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-04-26 12:48:37 +05:30
render layout : false
end
2016-04-02 18:10:28 +05:30
def revert
2017-08-17 22:00:37 +05:30
assign_change_commit_vars
return render_404 if @start_branch . blank?
2016-04-02 18:10:28 +05:30
2017-08-17 22:00:37 +05:30
@branch_name = create_new_branch? ? @commit . revert_branch_name : @start_branch
2016-04-02 18:10:28 +05:30
2017-01-15 13:20:01 +05:30
create_commit ( Commits :: RevertService , success_notice : " The #{ @commit . change_type_title ( current_user ) } has been successfully reverted. " ,
2021-04-29 21:17:54 +05:30
success_path : - > { successful_change_path ( @project ) } , failure_path : failed_change_path )
2016-04-02 18:10:28 +05:30
end
2016-06-02 11:05:42 +05:30
def cherry_pick
2017-08-17 22:00:37 +05:30
assign_change_commit_vars
2015-11-26 14:37:03 +05:30
2017-08-17 22:00:37 +05:30
return render_404 if @start_branch . blank?
2021-04-29 21:17:54 +05:30
target_project = find_cherry_pick_target_project
return render_404 unless target_project
2017-08-17 22:00:37 +05:30
@branch_name = create_new_branch? ? @commit . cherry_pick_branch_name : @start_branch
2016-06-02 11:05:42 +05:30
2018-11-20 20:47:30 +05:30
create_commit ( Commits :: CherryPickService , success_notice : " The #{ @commit . change_type_title ( current_user ) } has been successfully cherry-picked into #{ @branch_name } . " ,
2021-04-29 21:17:54 +05:30
success_path : - > { successful_change_path ( target_project ) } ,
failure_path : failed_change_path ,
target_project : target_project )
2016-04-02 18:10:28 +05:30
end
2016-06-02 11:05:42 +05:30
private
2017-08-17 22:00:37 +05:30
def create_new_branch?
params [ :create_merge_request ] . present? || ! can? ( current_user , :push_code , @project )
end
2021-04-29 21:17:54 +05:30
def successful_change_path ( target_project )
referenced_merge_request_url || project_commits_url ( target_project , @branch_name )
2016-04-02 18:10:28 +05:30
end
2016-06-02 11:05:42 +05:30
def failed_change_path
2017-09-10 17:25:29 +05:30
referenced_merge_request_url || project_commit_url ( @project , params [ :id ] )
2016-04-02 18:10:28 +05:30
end
def referenced_merge_request_url
2017-01-15 13:20:01 +05:30
if merge_request = @commit . merged_merge_request ( current_user )
2017-09-10 17:25:29 +05:30
project_merge_request_url ( merge_request . target_project , merge_request )
2017-01-15 13:20:01 +05:30
end
2016-04-02 18:10:28 +05:30
end
2014-09-02 18:07:02 +05:30
def commit
2018-11-18 11:00:15 +05:30
@noteable = @commit || = @project . commit_by ( oid : params [ :id ] ) . tap do | commit |
# preload author and their status for rendering
commit & . author & . status
end
2014-09-02 18:07:02 +05:30
end
2015-11-26 14:37:03 +05:30
2016-08-24 12:49:21 +05:30
def define_commit_vars
2016-04-02 18:10:28 +05:30
return git_not_found! unless commit
2016-06-02 11:05:42 +05:30
opts = diff_options
opts [ :ignore_whitespace_change ] = true if params [ :format ] == 'diff'
2015-12-23 02:04:40 +05:30
2016-06-02 11:05:42 +05:30
@diffs = commit . diffs ( opts )
2015-11-26 14:37:03 +05:30
@notes_count = commit . notes . count
2017-08-17 22:00:37 +05:30
2021-06-08 01:23:25 +05:30
@environment = :: Environments :: EnvironmentsByDeploymentsFinder . new ( @project , current_user , commit : @commit , find_latest : true ) . execute . last
2016-08-24 12:49:21 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2016-08-24 12:49:21 +05:30
def define_note_vars
2017-08-17 22:00:37 +05:30
@noteable = @commit
2016-08-24 12:49:21 +05:30
@note = @project . build_commit_note ( commit )
2017-08-17 22:00:37 +05:30
@new_diff_note_attrs = {
2016-08-24 12:49:21 +05:30
noteable_type : 'Commit' ,
commit_id : @commit . id
}
2015-12-23 02:04:40 +05:30
2017-08-17 22:00:37 +05:30
@grouped_diff_discussions = commit . grouped_diff_discussions
@discussions = commit . discussions
2018-03-17 18:26:18 +05:30
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-08-17 22:00:37 +05:30
@notes = ( @grouped_diff_discussions . values . flatten + @discussions ) . flat_map ( & :notes )
2018-03-17 18:26:18 +05:30
@notes = prepare_notes_for_rendering ( @notes , @commit )
2015-11-26 14:37:03 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2015-11-26 14:37:03 +05:30
2021-04-17 20:07:23 +05:30
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-08-17 22:00:37 +05:30
def assign_change_commit_vars
@start_branch = params [ :start_branch ]
@commit_params = { commit : @commit }
2015-11-26 14:37:03 +05:30
end
2021-04-29 21:17:54 +05:30
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
2014-09-02 18:07:02 +05:30
end