Skip to content
Snippets Groups Projects

Users can apply multiple suggestions at once.

Merged Jesse Hall requested to merge jessehall3/gitlab-ee:25486-batch-suggestions into master
3 files
+ 70
49
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -7,7 +7,7 @@ class ApplyService < ::BaseService
PLACEHOLDERS = {
'project_path' => ->(suggestions, user) { suggestions[0].project.path },
'project_name' => ->(suggestions, user) { suggestions[0].project.name },
'file_paths' => ->(suggestions, user) { suggestions.map(&:file_path).uniq.sort.join("\n") },
'file_paths' => ->(suggestions, user) { format_paths(suggestions.map(&:file_path))},
'branch_name' => ->(suggestions, user) { suggestions[0].branch },
'suggestions_count' => ->(suggestions, user) { suggestions.size },
'username' => ->(suggestions, user) { user.username },
@@ -26,48 +26,56 @@ def initialize(current_user)
end
def execute(*suggestions)
blobs_data = {}
error_message, blobs_data = build_blobs_data(suggestions)
if error_message
error(error_message)
else
result(suggestions, blobs_data)
end
rescue Files::MultiService::FileChangedError
error(_('A file has been changed'))
end
def self.format_paths(paths)
paths.uniq.sort.join("\n")
end
private
def build_blobs_data(suggestions)
blob_data_by_path = {}
error_message = nil
suggestions.each do |suggestion|
error_message = detect_suggestion_error(suggestion, blobs_data)
error_message = detect_suggestion_error(suggestion, blob_data_by_path)
if error_message
break
end
add_suggestion_lines(suggestion, blobs_data)
add_line_range_info(suggestion, blob_data_by_path)
end
if error_message
error(error_message)
else
result(suggestions, blobs_data.values)
end
rescue Files::MultiService::FileChangedError
error(_('A file has been changed'))
[error_message, blob_data_by_path.values]
end
private
def add_suggestion_lines(suggestion, blobs_data)
def add_line_range_info(suggestion, blob_data_by_path)
file_path = suggestion.diff_file.file_path
blob_data = blobs_data[file_path] ||= {
blob_data = blob_data_by_path[file_path] ||= {
blob: suggestion.diff_file.new_blob,
new_lines_info: []
line_ranges_info: []
}
new_line_info = {
blob_data[:line_ranges_info] << {
range: suggestion.from_line_index..suggestion.to_line_index,
content: suggestion.to_content
}
blob_data[:new_lines_info] << new_line_info
end
def result(suggestions, blobs_data_values)
file_update_params = file_update_params(suggestions, blobs_data_values)
def result(suggestions, blobs_data)
file_update_params = file_update_params(suggestions, blobs_data)
multi_service = ::Files::MultiService.new(suggestions[0].project, current_user, file_update_params)
multi_service.execute.tap do |result|
@@ -81,9 +89,9 @@ def update_suggestions(suggestions, result)
end
end
def file_update_params(suggestions, blobs_data_values)
def file_update_params(suggestions, blobs_data)
commit_message = processed_suggestions_commit_message(suggestions)
actions = actions(suggestions[0].project, blobs_data_values)
actions = actions(suggestions[0].project, blobs_data)
branch_name = suggestions[0].branch
{
@@ -94,8 +102,8 @@ def file_update_params(suggestions, blobs_data_values)
}
end
def actions(project, blobs_data_values)
blobs_data_values.map do |blob_data|
def actions(project, blobs_data)
blobs_data.map do |blob_data|
blob = blob_data[:blob]
file_content = new_file_content(blob_data)
file_last_commit = Gitlab::Git::Commit.last_for_path(project.repository, blob.commit_id, blob.path)
@@ -113,9 +121,9 @@ def new_file_content(blob_data)
blob_data[:blob].load_all_data!
content = blob_data[:blob].data.lines
blob_data[:new_lines_info].each do |line_info|
range = line_info[:range]
content[range] = line_info[:content]
blob_data[:line_ranges_info].each do |range_info|
range = range_info[:range]
content[range] = range_info[:content]
end
content.join
@@ -133,7 +141,7 @@ def processed_suggestions_commit_message(suggestions)
end
end
def detect_suggestion_error(suggestion, blobs_data)
def detect_suggestion_error(suggestion, blob_data_by_path)
unless suggestion.appliable?(cached: false)
return _('A suggestion is not applicable')
end
@@ -146,7 +154,7 @@ def detect_suggestion_error(suggestion, blobs_data)
return _('A file was not found')
end
if has_range_conflict?(suggestion, blobs_data)
if has_range_conflict?(suggestion, blob_data_by_path)
return _('Suggestions are not applicable as their lines cannot overlap')
end
@@ -160,7 +168,7 @@ def has_range_conflict?(suggestion, blobs_data)
new_range = suggestion.from_line_index..suggestion.to_line_index
current_ranges = blob_data[:new_lines_info].map { |line_info| line_info[:range] }
current_ranges = blob_data[:line_ranges_info].map { |range_info| range_info[:range] }
current_ranges.any? do |current_range|
current_range.overlaps?(new_range)
Loading