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:
		
							parent
							
								
									ebe0d34128
								
							
						
					
					
						commit
						5f232b5687
					
				|  | @ -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. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue