summaryrefslogtreecommitdiff
path: root/app/services/suggestions
diff options
context:
space:
mode:
authorOswaldo Ferreira <oswaldo@gitlab.com>2019-01-10 10:38:15 -0200
committerOswaldo Ferreira <oswaldo@gitlab.com>2019-01-11 21:35:07 -0200
commit6e293681180870e16cb102817dd588b0357cabca (patch)
tree9c0bc2528d35e32f00287ec6509baa2e15874182 /app/services/suggestions
parent49f538c766f3b4f8fb7436afd472f88291a7c76e (diff)
downloadgitlab-ce-6e293681180870e16cb102817dd588b0357cabca.tar.gz
Adjust applied suggestion reverting previous changes
1. Avoid suggestions being applied on the same file from reverting previous changes 2. Gracefully use and handle file changes error when updating the file (though, it does not totally solves the sync problem for multiple suggestion applications at once)
Diffstat (limited to 'app/services/suggestions')
-rw-r--r--app/services/suggestions/apply_service.rb34
1 files changed, 26 insertions, 8 deletions
diff --git a/app/services/suggestions/apply_service.rb b/app/services/suggestions/apply_service.rb
index d931d528c86..cc47b46b527 100644
--- a/app/services/suggestions/apply_service.rb
+++ b/app/services/suggestions/apply_service.rb
@@ -11,6 +11,10 @@ module Suggestions
return error('Suggestion is not appliable')
end
+ unless latest_diff_refs?(suggestion)
+ return error('The file has been changed')
+ end
+
params = file_update_params(suggestion)
result = ::Files::UpdateService.new(suggestion.project, @current_user, params).execute
@@ -19,30 +23,44 @@ module Suggestions
end
result
+ rescue Files::UpdateService::FileChangedError
+ error('The file has been changed')
end
private
- def file_update_params(suggestion)
- diff_file = suggestion.diff_file
+ # Checks whether the latest diff refs for the branch matches with
+ # the position refs we're using to update the file content. Since
+ # the persisted refs are updated async (for MergeRequest),
+ # it's more consistent to fetch this data directly from the repository.
+ def latest_diff_refs?(suggestion)
+ suggestion.position.diff_refs == suggestion.noteable.repository_diff_refs
+ end
- file_path = diff_file.file_path
- branch_name = suggestion.noteable.source_branch
- file_content = new_file_content(suggestion)
+ def file_update_params(suggestion)
+ blob = suggestion.diff_file.new_blob
+ file_path = suggestion.file_path
+ branch_name = suggestion.branch
+ file_content = new_file_content(suggestion, blob)
commit_message = "Apply suggestion to #{file_path}"
+ file_last_commit =
+ Gitlab::Git::Commit.last_for_path(suggestion.project.repository,
+ blob.commit_id,
+ blob.path)
+
{
file_path: file_path,
branch_name: branch_name,
start_branch: branch_name,
commit_message: commit_message,
- file_content: file_content
+ file_content: file_content,
+ last_commit_sha: file_last_commit&.id
}
end
- def new_file_content(suggestion)
+ def new_file_content(suggestion, blob)
range = suggestion.from_line_index..suggestion.to_line_index
- blob = suggestion.diff_file.new_blob
blob.load_all_data!
content = blob.data.lines