diff options
author | Frank West <frank.west.iii@gmail.com> | 2016-08-08 06:29:23 +0300 |
---|---|---|
committer | Frank West <frank.west.iii@gmail.com> | 2016-08-15 05:34:55 +0300 |
commit | ade0c2c8922c0838ba85cf69419cbb109453d6b2 (patch) | |
tree | 34631dfd4d42827c94cb7b4883b2f0127d63964e /spec/services/files | |
parent | 30f5b9a5b711b46f1065baf755e413ceced5646b (diff) |
Prevents accidental overwrites of commits from UI
Currently when a user performs an update of a file through the UI and there
has already been a change committed to the file the previous commits will be
overwritten without a check to see if the file has been changed.
This commit uses the last commit sha at the time the user starts editing the
file and compares it with the current sha of the file being edited to ensure
they are the same before committing the file. If the shas do not match we
throw an exception preventing the commit from the commit from occurring.
Fixes #5857
Diffstat (limited to 'spec/services/files')
-rw-r--r-- | spec/services/files/update_service_spec.rb | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/spec/services/files/update_service_spec.rb b/spec/services/files/update_service_spec.rb new file mode 100644 index 00000000000..d019e50649f --- /dev/null +++ b/spec/services/files/update_service_spec.rb @@ -0,0 +1,84 @@ +require "spec_helper" + +describe Files::UpdateService do + subject { described_class.new(project, user, commit_params) } + + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:file_path) { 'files/ruby/popen.rb' } + let(:new_contents) { "New Content" } + let(:commit_params) do + { + file_path: file_path, + commit_message: "Update File", + file_content: new_contents, + file_content_encoding: "text", + last_commit_sha: last_commit_sha, + source_project: project, + source_branch: project.default_branch, + target_branch: project.default_branch, + } + end + + before do + project.team << [user, :master] + end + + describe "#execute" do + context "when the file's last commit sha does not match the supplied last_commit_sha" do + let(:last_commit_sha) { "foo" } + + it "returns a hash with the correct error message and a :error status " do + expect { subject.execute }. + to raise_error(Files::UpdateService::FileChangedError, + "You are attempting to update a file that has changed since you started editing it.") + end + end + + context "when the file's last commit sha does match the supplied last_commit_sha" do + let(:last_commit_sha) { Gitlab::Git::Commit.last_for_path(project.repository, project.default_branch, file_path).sha } + + it "returns a hash with the :success status " do + results = subject.execute + + expect(results).to match({ status: :success }) + end + + it "updates the file with the new contents" do + subject.execute + + results = project.repository.blob_at_branch(project.default_branch, file_path) + + expect(results.data).to eq(new_contents) + end + end + + context "when the last_commit_sha is not supplied" do + let(:commit_params) do + { + file_path: file_path, + commit_message: "Update File", + file_content: new_contents, + file_content_encoding: "text", + source_project: project, + source_branch: project.default_branch, + target_branch: project.default_branch, + } + end + + it "returns a hash with the :success status " do + results = subject.execute + + expect(results).to match({ status: :success }) + end + + it "updates the file with the new contents" do + subject.execute + + results = project.repository.blob_at_branch(project.default_branch, file_path) + + expect(results.data).to eq(new_contents) + end + end + end +end |