2018-07-16 12:31:01 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-04-19 20:37:44 -04:00
|
|
|
module Commits
|
|
|
|
class CreateService < ::BaseService
|
|
|
|
ValidationError = Class.new(StandardError)
|
2019-11-13 22:06:25 -05:00
|
|
|
class ChangeError < StandardError
|
|
|
|
attr_reader :error_code
|
|
|
|
|
|
|
|
def initialize(message, error_code = nil)
|
|
|
|
super(message)
|
|
|
|
|
|
|
|
@error_code = error_code
|
|
|
|
end
|
|
|
|
end
|
2017-04-19 20:37:44 -04:00
|
|
|
|
|
|
|
def initialize(*args)
|
|
|
|
super
|
|
|
|
|
|
|
|
@start_project = params[:start_project] || @project
|
|
|
|
@start_branch = params[:start_branch]
|
2019-06-13 06:44:41 -04:00
|
|
|
@start_sha = params[:start_sha]
|
2017-04-19 20:37:44 -04:00
|
|
|
@branch_name = params[:branch_name]
|
2019-03-06 05:44:59 -05:00
|
|
|
@force = params[:force] || false
|
2020-07-30 14:09:39 -04:00
|
|
|
@dry_run = params[:dry_run] || false
|
2017-04-19 20:37:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def execute
|
|
|
|
validate!
|
|
|
|
|
|
|
|
new_commit = create_commit!
|
|
|
|
|
|
|
|
success(result: new_commit)
|
2019-11-13 22:06:25 -05:00
|
|
|
rescue ChangeError => ex
|
2020-06-11 08:08:54 -04:00
|
|
|
Gitlab::ErrorTracking.log_exception(ex)
|
2019-11-13 22:06:25 -05:00
|
|
|
error(ex.message, pass_back: { error_code: ex.error_code })
|
2018-10-24 12:01:44 -04:00
|
|
|
rescue ValidationError,
|
|
|
|
Gitlab::Git::Index::IndexError,
|
|
|
|
Gitlab::Git::CommitError,
|
|
|
|
Gitlab::Git::PreReceiveError,
|
|
|
|
Gitlab::Git::CommandError => ex
|
2020-06-11 08:08:54 -04:00
|
|
|
Gitlab::ErrorTracking.log_exception(ex)
|
2017-04-19 20:37:44 -04:00
|
|
|
error(ex.message)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def create_commit!
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def raise_error(message)
|
|
|
|
raise ValidationError, message
|
|
|
|
end
|
|
|
|
|
|
|
|
def different_branch?
|
2019-06-13 06:44:41 -04:00
|
|
|
@start_project != @project || @start_branch != @branch_name || @start_sha.present?
|
2017-04-19 20:37:44 -04:00
|
|
|
end
|
|
|
|
|
2019-03-06 05:44:59 -05:00
|
|
|
def force?
|
|
|
|
!!@force
|
|
|
|
end
|
|
|
|
|
2017-04-19 20:37:44 -04:00
|
|
|
def validate!
|
|
|
|
validate_permissions!
|
2019-06-13 06:44:41 -04:00
|
|
|
validate_start_sha!
|
2017-04-19 20:37:44 -04:00
|
|
|
validate_on_branch!
|
2019-02-25 03:19:36 -05:00
|
|
|
validate_branch_existence!
|
2017-04-19 20:37:44 -04:00
|
|
|
|
|
|
|
validate_new_branch_name! if different_branch?
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_permissions!
|
2020-07-21 14:09:45 -04:00
|
|
|
allowed = ::Gitlab::UserAccess.new(current_user, container: project).can_push_to_branch?(@branch_name)
|
2017-04-19 20:37:44 -04:00
|
|
|
|
|
|
|
unless allowed
|
|
|
|
raise_error("You are not allowed to push into this branch")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-13 06:44:41 -04:00
|
|
|
def validate_start_sha!
|
|
|
|
return unless @start_sha
|
|
|
|
|
|
|
|
if @start_branch
|
|
|
|
raise_error("You can't pass both start_branch and start_sha")
|
|
|
|
elsif !Gitlab::Git.commit_id?(@start_sha)
|
|
|
|
raise_error("Invalid start_sha '#{@start_sha}'")
|
|
|
|
elsif !@start_project.repository.commit(@start_sha)
|
|
|
|
raise_error("Cannot find start_sha '#{@start_sha}'")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-19 20:37:44 -04:00
|
|
|
def validate_on_branch!
|
2019-06-13 06:44:41 -04:00
|
|
|
return unless @start_branch
|
|
|
|
|
2017-04-19 20:37:44 -04:00
|
|
|
if !@start_project.empty_repo? && !@start_project.repository.branch_exists?(@start_branch)
|
|
|
|
raise_error('You can only create or edit files when you are on a branch')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-02-25 03:19:36 -05:00
|
|
|
def validate_branch_existence!
|
2019-03-06 05:44:59 -05:00
|
|
|
if !project.empty_repo? && different_branch? && repository.branch_exists?(@branch_name) && !force?
|
2017-04-19 20:37:44 -04:00
|
|
|
raise_error("A branch called '#{@branch_name}' already exists. Switch to that branch in order to make changes")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_new_branch_name!
|
2019-12-03 13:06:49 -05:00
|
|
|
result = ::Branches::ValidateNewService.new(project).execute(@branch_name, force: force?)
|
2017-04-19 20:37:44 -04:00
|
|
|
|
|
|
|
if result[:status] == :error
|
|
|
|
raise_error("Something went wrong when we tried to create '#{@branch_name}' for you: #{result[:message]}")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-09-13 09:26:31 -04:00
|
|
|
|
|
|
|
Commits::CreateService.prepend_if_ee('EE::Commits::CreateService')
|