Improve error messages when file editing fails

Give more specific errors in API responses and web UI flash messages
when a file update fails.
This commit is contained in:
Vinnie Okada 2015-02-22 16:01:49 -07:00
parent ebe0d34128
commit 5f232b5687
7 changed files with 66 additions and 19 deletions

View File

@ -1,6 +1,7 @@
v 7.9.0 (unreleased) v 7.9.0 (unreleased)
- Move labels/milestones tabs to sidebar - Move labels/milestones tabs to sidebar
- Upgrade Rails gem to version 4.1.9. - Upgrade Rails gem to version 4.1.9.
- Improve error messages for file edit failures
- Improve UI for commits, issues and merge request lists - Improve UI for commits, issues and merge request lists
- Fix commit comments on first line of diff not rendering in Merge Request Discussion view. - Fix commit comments on first line of diff not rendering in Merge Request Discussion view.

View File

@ -37,11 +37,14 @@ class BaseService
private private
def error(message) def error(message, http_status = nil)
{ result = {
message: message, message: message,
status: :error status: :error
} }
result[:http_status] = http_status if http_status
result
end end
def success def success

View File

@ -20,17 +20,19 @@ module Files
end end
edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path) edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
created_successfully = edit_file_action.commit!( edit_file_action.commit!(
params[:content], params[:content],
params[:commit_message], params[:commit_message],
params[:encoding] params[:encoding]
) )
if created_successfully success
success rescue Gitlab::Satellite::CheckoutFailed => ex
else error("Your changes could not be committed because ref '#{ref}' could not be checked out", 400)
error("Your changes could not be committed. Maybe the file was changed by another process or there was nothing to commit?") rescue Gitlab::Satellite::CommitFailed => ex
end error("Your changes could not be committed. Maybe there was nothing to commit?", 409)
rescue Gitlab::Satellite::PushFailed => ex
error("Your changes could not be committed. Maybe the file was changed by another process?", 409)
end end
end end
end end

View File

@ -117,7 +117,8 @@ module API
branch_name: branch_name branch_name: branch_name
} }
else else
render_api_error!(result[:message], 400) http_status = result[:http_status] || 400
render_api_error!(result[:message], http_status)
end end
end end

View File

@ -15,7 +15,11 @@ module Gitlab
prepare_satellite!(repo) prepare_satellite!(repo)
# create target branch in satellite at the corresponding commit from bare repo # create target branch in satellite at the corresponding commit from bare repo
repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}") begin
repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}")
rescue Grit::Git::CommandFailed => ex
log_and_raise(CheckoutFailed, ex.message)
end
# update the file in the satellite's working dir # update the file in the satellite's working dir
file_path_in_satellite = File.join(repo.working_dir, file_path) file_path_in_satellite = File.join(repo.working_dir, file_path)
@ -31,19 +35,31 @@ module Gitlab
# commit the changes # commit the changes
# will raise CommandFailed when commit fails # will raise CommandFailed when commit fails
repo.git.commit(raise: true, timeout: true, a: true, m: commit_message) begin
repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
rescue Grit::Git::CommandFailed => ex
log_and_raise(CommitFailed, ex.message)
end
# push commit back to bare repo # push commit back to bare repo
# will raise CommandFailed when push fails # will raise CommandFailed when push fails
repo.git.push({ raise: true, timeout: true }, :origin, ref) begin
repo.git.push({ raise: true, timeout: true }, :origin, ref)
rescue Grit::Git::CommandFailed => ex
log_and_raise(PushFailed, ex.message)
end
# everything worked # everything worked
true true
end end
rescue Grit::Git::CommandFailed => ex end
Gitlab::GitLogger.error(ex.message)
false private
def log_and_raise(errorClass, message)
Gitlab::GitLogger.error(message)
raise(errorClass, message)
end end
end end
end end

View File

@ -1,5 +1,9 @@
module Gitlab module Gitlab
module Satellite module Satellite
class CheckoutFailed < StandardError; end
class CommitFailed < StandardError; end
class PushFailed < StandardError; end
class Satellite class Satellite
include Gitlab::Popen include Gitlab::Popen

View File

@ -98,13 +98,33 @@ describe API::API, api: true do
expect(response.status).to eq(400) expect(response.status).to eq(400)
end end
it "should return a 400 if satellite fails to create file" do it 'should return a 400 if the checkout fails' do
Gitlab::Satellite::EditFileAction.any_instance.stub( Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
commit!: false, .and_raise(Gitlab::Satellite::CheckoutFailed)
)
put api("/projects/#{project.id}/repository/files", user), valid_params put api("/projects/#{project.id}/repository/files", user), valid_params
expect(response.status).to eq(400) expect(response.status).to eq(400)
ref = valid_params[:branch_name]
expect(response.body).to match("ref '#{ref}' could not be checked out")
end
it 'should return a 409 if the file was not modified' do
Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
.and_raise(Gitlab::Satellite::CommitFailed)
put api("/projects/#{project.id}/repository/files", user), valid_params
expect(response.status).to eq(409)
expect(response.body).to match("Maybe there was nothing to commit?")
end
it 'should return a 409 if the push fails' do
Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
.and_raise(Gitlab::Satellite::PushFailed)
put api("/projects/#{project.id}/repository/files", user), valid_params
expect(response.status).to eq(409)
expect(response.body).to match("Maybe the file was changed by another process?")
end end
end end