Commit 1110def8 authored by Roman Safronov's avatar Roman Safronov Committed by Grzegorz Bizon

Introduce optimistic locking support via optional parameter last_commit_id on File Update API

parent 9f3a1203
---
title: 'Introduce optimistic locking support via optional parameter last_commit_sha on File Update API'
merge_request: 11694
author: electroma
...@@ -111,6 +111,7 @@ Parameters: ...@@ -111,6 +111,7 @@ Parameters:
- `author_name` (optional) - Specify the commit author's name - `author_name` (optional) - Specify the commit author's name
- `content` (required) - New file content - `content` (required) - New file content
- `commit_message` (required) - Commit message - `commit_message` (required) - Commit message
- `last_commit_id` (optional) - Last known file commit id
If the commit fails for any reason we return a 400 error with a non-specific If the commit fails for any reason we return a 400 error with a non-specific
error message. Possible causes for a failed commit include: error message. Possible causes for a failed commit include:
......
...@@ -10,7 +10,8 @@ module API ...@@ -10,7 +10,8 @@ module API
file_content: attrs[:content], file_content: attrs[:content],
file_content_encoding: attrs[:encoding], file_content_encoding: attrs[:encoding],
author_email: attrs[:author_email], author_email: attrs[:author_email],
author_name: attrs[:author_name] author_name: attrs[:author_name],
last_commit_sha: attrs[:last_commit_id]
} }
end end
...@@ -46,6 +47,7 @@ module API ...@@ -46,6 +47,7 @@ module API
use :simple_file_params use :simple_file_params
requires :content, type: String, desc: 'File content' requires :content, type: String, desc: 'File content'
optional :encoding, type: String, values: %w[base64], desc: 'File encoding' optional :encoding, type: String, values: %w[base64], desc: 'File encoding'
optional :last_commit_id, type: String, desc: 'Last known commit id for this file'
end end
end end
...@@ -111,7 +113,12 @@ module API ...@@ -111,7 +113,12 @@ module API
authorize! :push_code, user_project authorize! :push_code, user_project
file_params = declared_params(include_missing: false) file_params = declared_params(include_missing: false)
result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute
begin
result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute
rescue ::Files::UpdateService::FileChangedError => e
render_api_error!(e.message, 400)
end
if result[:status] == :success if result[:status] == :success
status(200) status(200)
......
...@@ -258,6 +258,25 @@ describe API::Files do ...@@ -258,6 +258,25 @@ describe API::Files do
expect(last_commit.author_name).to eq(user.name) expect(last_commit.author_name).to eq(user.name)
end end
it "returns a 400 bad request if update existing file with stale last commit id" do
params_with_stale_id = valid_params.merge(last_commit_id: 'stale')
put api(route(file_path), user), params_with_stale_id
expect(response).to have_http_status(400)
expect(json_response['message']).to eq('You are attempting to update a file that has changed since you started editing it.')
end
it "updates existing file in project repo with accepts correct last commit id" do
last_commit = Gitlab::Git::Commit
.last_for_path(project.repository, 'master', URI.unescape(file_path))
params_with_correct_id = valid_params.merge(last_commit_id: last_commit.id)
put api(route(file_path), user), params_with_correct_id
expect(response).to have_http_status(200)
end
it "returns a 400 bad request if no params given" do it "returns a 400 bad request if no params given" do
put api(route(file_path), user) put api(route(file_path), user)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment