diff options
author | Roman Safronov <electroma@gmail.com> | 2017-06-06 13:55:29 +0000 |
---|---|---|
committer | Grzegorz Bizon <grzegorz@gitlab.com> | 2017-06-06 13:55:29 +0000 |
commit | 1110def8e21d4927a127783d468fbddf3cc886c7 (patch) | |
tree | ef057bd6a3e1d7964723e6364e44ec1fe2c3ae45 | |
parent | 9f3a1203dfd3452a929dc70d9b25cbf2457c353a (diff) | |
download | gitlab-ce-1110def8e21d4927a127783d468fbddf3cc886c7.tar.gz |
Introduce optimistic locking support via optional parameter last_commit_id on File Update API
-rw-r--r-- | changelogs/unreleased/32642_last_commit_id_in_file_api.yml | 4 | ||||
-rw-r--r-- | doc/api/repository_files.md | 1 | ||||
-rw-r--r-- | lib/api/files.rb | 11 | ||||
-rw-r--r-- | spec/requests/api/files_spec.rb | 19 |
4 files changed, 33 insertions, 2 deletions
diff --git a/changelogs/unreleased/32642_last_commit_id_in_file_api.yml b/changelogs/unreleased/32642_last_commit_id_in_file_api.yml new file mode 100644 index 00000000000..80435352e10 --- /dev/null +++ b/changelogs/unreleased/32642_last_commit_id_in_file_api.yml @@ -0,0 +1,4 @@ +--- +title: 'Introduce optimistic locking support via optional parameter last_commit_sha on File Update API' +merge_request: 11694 +author: electroma diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index 0b5782a8cc4..18ceb8f779e 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -111,6 +111,7 @@ Parameters: - `author_name` (optional) - Specify the commit author's name - `content` (required) - New file content - `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 error message. Possible causes for a failed commit include: diff --git a/lib/api/files.rb b/lib/api/files.rb index e6ea12c5ab7..25b0968a271 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -10,7 +10,8 @@ module API file_content: attrs[:content], file_content_encoding: attrs[:encoding], author_email: attrs[:author_email], - author_name: attrs[:author_name] + author_name: attrs[:author_name], + last_commit_sha: attrs[:last_commit_id] } end @@ -46,6 +47,7 @@ module API use :simple_file_params requires :content, type: String, desc: 'File content' 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 @@ -111,7 +113,12 @@ module API authorize! :push_code, user_project 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 status(200) diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index deb2cac6869..d325c6eff9d 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -258,6 +258,25 @@ describe API::Files do expect(last_commit.author_name).to eq(user.name) 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 put api(route(file_path), user) |