Commit f2f84469 authored by Sean McGivern's avatar Sean McGivern Committed by Fatih Acet

Handle conflict resolution errors in controller

parent 97ceadee
...@@ -139,15 +139,25 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -139,15 +139,25 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render 'show' render 'show'
end end
format.json { render json: Gitlab::Conflict::FileCollection.new(@merge_request) } format.json do
begin
render json: Gitlab::Conflict::FileCollection.new(@merge_request)
rescue Gitlab::Conflict::Parser::ParserError => e
render json: { message: 'Unable to resolve conflicts in the web interface for this merge request' }
end
end
end end
end end
def resolve_conflicts def resolve_conflicts
begin
Gitlab::Conflict::FileCollection.new(@merge_request).resolve_conflicts!(params[:merge_request], nil, user: current_user) Gitlab::Conflict::FileCollection.new(@merge_request).resolve_conflicts!(params[:merge_request], nil, user: current_user)
redirect_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), redirect_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request),
notice: 'Merge conflicts resolved. The merge request can now be merged.' notice: 'Merge conflicts resolved. The merge request can now be merged.'
rescue Gitlab::Conflict::File::MissingResolution => e
render status: :bad_request, json: { message: e.message }
end
end end
def builds def builds
......
...@@ -35,23 +35,23 @@ module Gitlab ...@@ -35,23 +35,23 @@ module Gitlab
end end
def resolve_lines(resolution) def resolve_lines(resolution)
current_section = nil section_id = nil
lines.map do |line| lines.map do |line|
unless line.type unless line.type
current_section = nil section_id = nil
next line next line
end end
current_section ||= resolution[line_code(line)] section_id ||= line_code(line)
case current_section case resolution[section_id]
when 'ours' when 'ours'
next unless line.type == 'new' next unless line.type == 'new'
when 'theirs' when 'theirs'
next unless line.type == 'old' next unless line.type == 'old'
else else
raise MissingResolution raise MissingResolution, "Missing resolution for section ID: #{section_id}"
end end
line line
......
module Gitlab module Gitlab
module Conflict module Conflict
class Parser class Parser
class UnexpectedDelimiter < StandardError class ParserError < StandardError
end end
class MissingEndDelimiter < StandardError class UnexpectedDelimiter < ParserError
end
class MissingEndDelimiter < ParserError
end end
def parse(text, our_path:, their_path:, parent: nil) def parse(text, our_path:, their_path:, parent: nil)
......
...@@ -530,8 +530,13 @@ describe Projects::MergeRequestsController do ...@@ -530,8 +530,13 @@ describe Projects::MergeRequestsController do
end end
describe 'GET conflicts' do describe 'GET conflicts' do
context 'as JSON' do let(:json_response) { JSON.parse(response.body) }
context 'when the conflicts cannot be resolved in the UI' do
before do before do
allow_any_instance_of(Gitlab::Conflict::Parser).
to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnexpectedDelimiter)
get :conflicts, get :conflicts,
namespace_id: merge_request_with_conflicts.project.namespace.to_param, namespace_id: merge_request_with_conflicts.project.namespace.to_param,
project_id: merge_request_with_conflicts.project.to_param, project_id: merge_request_with_conflicts.project.to_param,
...@@ -539,7 +544,23 @@ describe Projects::MergeRequestsController do ...@@ -539,7 +544,23 @@ describe Projects::MergeRequestsController do
format: 'json' format: 'json'
end end
let(:json_response) { JSON.parse(response.body) } it 'returns a 200 status code' do
expect(response).to have_http_status(:ok)
end
it 'returns JSON with a message' do
expect(json_response.keys).to contain_exactly('message')
end
end
context 'with valid conflicts' do
before do
get :conflicts,
namespace_id: merge_request_with_conflicts.project.namespace.to_param,
project_id: merge_request_with_conflicts.project.to_param,
id: merge_request_with_conflicts.iid,
format: 'json'
end
it 'includes meta info about the MR' do it 'includes meta info about the MR' do
expect(json_response['commit_message']).to include('Merge branch') expect(json_response['commit_message']).to include('Merge branch')
...@@ -589,6 +610,9 @@ describe Projects::MergeRequestsController do ...@@ -589,6 +610,9 @@ describe Projects::MergeRequestsController do
end end
context 'POST resolve_conflicts' do context 'POST resolve_conflicts' do
let(:json_response) { JSON.parse(response.body) }
let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha }
def resolve_conflicts(params) def resolve_conflicts(params)
post :resolve_conflicts, post :resolve_conflicts,
namespace_id: merge_request_with_conflicts.project.namespace.to_param, namespace_id: merge_request_with_conflicts.project.namespace.to_param,
...@@ -607,6 +631,7 @@ describe Projects::MergeRequestsController do ...@@ -607,6 +631,7 @@ describe Projects::MergeRequestsController do
end end
it 'creates a new commit on the branch' do it 'creates a new commit on the branch' do
expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
expect(merge_request_with_conflicts.source_branch_head.message).to include('Merge branch') expect(merge_request_with_conflicts.source_branch_head.message).to include('Merge branch')
end end
...@@ -614,5 +639,23 @@ describe Projects::MergeRequestsController do ...@@ -614,5 +639,23 @@ describe Projects::MergeRequestsController do
expect(response).to redirect_to([merge_request_with_conflicts.target_project.namespace.becomes(Namespace), merge_request_with_conflicts.target_project, merge_request_with_conflicts]) expect(response).to redirect_to([merge_request_with_conflicts.target_project.namespace.becomes(Namespace), merge_request_with_conflicts.target_project, merge_request_with_conflicts])
end end
end end
context 'when sections are missing' do
before do
resolve_conflicts('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_4_4' => 'ours')
end
it 'returns a 400 error' do
expect(response).to have_http_status(:bad_request)
end
it 'has a message with the name of the first missing section' do
expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9')
end
it 'does not create a new commit' do
expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment