summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Safronov <electroma@gmail.com>2017-06-06 13:55:29 +0000
committerGrzegorz Bizon <grzegorz@gitlab.com>2017-06-06 13:55:29 +0000
commit1110def8e21d4927a127783d468fbddf3cc886c7 (patch)
treeef057bd6a3e1d7964723e6364e44ec1fe2c3ae45
parent9f3a1203dfd3452a929dc70d9b25cbf2457c353a (diff)
downloadgitlab-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.yml4
-rw-r--r--doc/api/repository_files.md1
-rw-r--r--lib/api/files.rb11
-rw-r--r--spec/requests/api/files_spec.rb19
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)