f8cecafb07
When passing start_branch on committing from the WebIDE, it's possible that the branch has changed since editing started, which results in the change being applied on top of the latest commit in the branch and overwriting the new changes. By passing the start_sha instead we can make sure that the change is applied on top of the commit which the user started editing from.
73 lines
2 KiB
Ruby
73 lines
2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Files
|
|
class MultiService < Files::BaseService
|
|
UPDATE_FILE_ACTIONS = %w(update move delete chmod).freeze
|
|
|
|
def create_commit!
|
|
transformer = Lfs::FileTransformer.new(project, repository, @branch_name)
|
|
|
|
actions = actions_after_lfs_transformation(transformer, params[:actions])
|
|
actions = transform_move_actions(actions)
|
|
|
|
commit_actions!(actions)
|
|
end
|
|
|
|
private
|
|
|
|
def actions_after_lfs_transformation(transformer, actions)
|
|
actions.map do |action|
|
|
if action[:action] == 'create'
|
|
result = transformer.new_file(action[:file_path], action[:content], encoding: action[:encoding])
|
|
action[:content] = result.content
|
|
action[:encoding] = result.encoding
|
|
end
|
|
|
|
action
|
|
end
|
|
end
|
|
|
|
# When moving a file, `content: nil` means "use the contents of the previous
|
|
# file", while `content: ''` means "move the file and set it to empty"
|
|
def transform_move_actions(actions)
|
|
actions.map do |action|
|
|
action[:infer_content] = true if action[:content].nil?
|
|
|
|
action
|
|
end
|
|
end
|
|
|
|
def commit_actions!(actions)
|
|
repository.multi_action(
|
|
current_user,
|
|
message: @commit_message,
|
|
branch_name: @branch_name,
|
|
actions: actions,
|
|
author_email: @author_email,
|
|
author_name: @author_name,
|
|
start_project: @start_project,
|
|
start_branch_name: @start_branch,
|
|
start_sha: @start_sha,
|
|
force: force?
|
|
)
|
|
rescue ArgumentError => e
|
|
raise_error(e)
|
|
end
|
|
|
|
def validate!
|
|
super
|
|
|
|
params[:actions].each { |action| validate_file_status!(action) }
|
|
end
|
|
|
|
def validate_file_status!(action)
|
|
return unless UPDATE_FILE_ACTIONS.include?(action[:action])
|
|
|
|
file_path = action[:previous_path] || action[:file_path]
|
|
|
|
if file_has_changed?(file_path, action[:last_commit_id])
|
|
raise_error("The file has changed since you started editing it: #{file_path}")
|
|
end
|
|
end
|
|
end
|
|
end
|