提交 b2553840 编写于 作者: S Sean McGivern

Merge branch 'conflict-resolution-refactor' into 'master'

Conflict resolution refactor

See merge request gitlab-org/gitlab-ce!14747
...@@ -53,7 +53,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap ...@@ -53,7 +53,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.' flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.'
render json: { redirect_to: project_merge_request_url(@project, @merge_request, resolved_conflicts: true) } render json: { redirect_to: project_merge_request_url(@project, @merge_request, resolved_conflicts: true) }
rescue Gitlab::Conflict::ResolutionError => e rescue Gitlab::Git::Conflict::Resolver::ResolutionError => e
render status: :bad_request, json: { message: e.message } render status: :bad_request, json: { message: e.message }
end end
end end
......
...@@ -468,9 +468,7 @@ class Repository ...@@ -468,9 +468,7 @@ class Repository
end end
def blob_at(sha, path) def blob_at(sha, path)
unless Gitlab::Git.blank_ref?(sha) Blob.decorate(raw_repository.blob_at(sha, path), project)
Blob.decorate(Gitlab::Git::Blob.find(self, sha, path), project)
end
rescue Gitlab::Git::Repository::NoRepository rescue Gitlab::Git::Repository::NoRepository
nil nil
end end
...@@ -914,14 +912,6 @@ class Repository ...@@ -914,14 +912,6 @@ class Repository
end end
end end
def resolve_conflicts(user, branch_name, params)
with_branch(user, branch_name) do
committer = user_to_committer(user)
create_commit(params.merge(author: committer, committer: committer))
end
end
def merged_to_root_ref?(branch_name) def merged_to_root_ref?(branch_name)
branch_commit = commit(branch_name) branch_commit = commit(branch_name)
root_ref_commit = commit(root_ref) root_ref_commit = commit(root_ref)
......
...@@ -23,13 +23,13 @@ module MergeRequests ...@@ -23,13 +23,13 @@ module MergeRequests
# when there are no conflict files. # when there are no conflict files.
conflicts.files.each(&:lines) conflicts.files.each(&:lines)
@conflicts_can_be_resolved_in_ui = conflicts.files.length > 0 @conflicts_can_be_resolved_in_ui = conflicts.files.length > 0
rescue Rugged::OdbError, Gitlab::Conflict::Parser::UnresolvableError, Gitlab::Conflict::FileCollection::ConflictSideMissing rescue Rugged::OdbError, Gitlab::Git::Conflict::Parser::UnresolvableError, Gitlab::Git::Conflict::Resolver::ConflictSideMissing
@conflicts_can_be_resolved_in_ui = false @conflicts_can_be_resolved_in_ui = false
end end
end end
def conflicts def conflicts
@conflicts ||= Gitlab::Conflict::FileCollection.read_only(merge_request) @conflicts ||= Gitlab::Conflict::FileCollection.new(merge_request)
end end
end end
end end
......
module MergeRequests module MergeRequests
module Conflicts module Conflicts
class ResolveService < MergeRequests::Conflicts::BaseService class ResolveService < MergeRequests::Conflicts::BaseService
MissingFiles = Class.new(Gitlab::Conflict::ResolutionError)
def execute(current_user, params) def execute(current_user, params)
rugged = merge_request.source_project.repository.rugged conflicts = Gitlab::Conflict::FileCollection.new(merge_request)
Gitlab::Conflict::FileCollection.for_resolution(merge_request) do |conflicts_for_resolution|
merge_index = conflicts_for_resolution.merge_index
params[:files].each do |file_params|
conflict_file = conflicts_for_resolution.file_for_path(file_params[:old_path], file_params[:new_path])
write_resolved_file_to_index(merge_index, rugged, conflict_file, file_params)
end
unless merge_index.conflicts.empty?
missing_files = merge_index.conflicts.map { |file| file[:ours][:path] }
raise MissingFiles, "Missing resolutions for the following files: #{missing_files.join(', ')}"
end
commit_params = {
message: params[:commit_message] || conflicts_for_resolution.default_commit_message,
parents: [conflicts_for_resolution.our_commit, conflicts_for_resolution.their_commit].map(&:oid),
tree: merge_index.write_tree(rugged)
}
conflicts_for_resolution
.project
.repository
.resolve_conflicts(current_user, merge_request.source_branch, commit_params)
end
end
private
def write_resolved_file_to_index(merge_index, rugged, file, params)
if params[:sections]
new_file = file.resolve_lines(params[:sections]).map(&:text).join("\n")
new_file << "\n" if file.our_blob.data.ends_with?("\n")
elsif params[:content]
new_file = file.resolve_content(params[:content])
end
our_path = file.our_path
merge_index.add(path: our_path, oid: rugged.write(new_file, :blob), mode: file.our_mode) conflicts.resolve(current_user, params[:commit_message], params[:files])
merge_index.conflict_remove(our_path)
end end
end end
end end
......
...@@ -186,7 +186,7 @@ module API ...@@ -186,7 +186,7 @@ module API
lines.each do |line| lines.each do |line|
next unless line.new_pos == params[:line] && line.type == params[:line_type] next unless line.new_pos == params[:line] && line.type == params[:line_type]
break opts[:line_code] = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos) break opts[:line_code] = Gitlab::Git.diff_line_code(diff.new_path, line.new_pos, line.old_pos)
end end
break if opts[:line_code] break if opts[:line_code]
......
...@@ -173,7 +173,7 @@ module API ...@@ -173,7 +173,7 @@ module API
lines.each do |line| lines.each do |line|
next unless line.new_pos == params[:line] && line.type == params[:line_type] next unless line.new_pos == params[:line] && line.type == params[:line_type]
break opts[:line_code] = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos) break opts[:line_code] = Gitlab::Git.diff_line_code(diff.new_path, line.new_pos, line.old_pos)
end end
break if opts[:line_code] break if opts[:line_code]
......
...@@ -23,7 +23,7 @@ module Github ...@@ -23,7 +23,7 @@ module Github
private private
def generate_line_code(line) def generate_line_code(line)
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) Gitlab::Git.diff_line_code(file_path, line.new_pos, line.old_pos)
end end
def on_diff? def on_diff?
......
...@@ -241,7 +241,7 @@ module Gitlab ...@@ -241,7 +241,7 @@ module Gitlab
end end
def generate_line_code(pr_comment) def generate_line_code(pr_comment)
Gitlab::Diff::LineCode.generate(pr_comment.file_path, pr_comment.new_pos, pr_comment.old_pos) Gitlab::Git.diff_line_code(pr_comment.file_path, pr_comment.new_pos, pr_comment.old_pos)
end end
def pull_request_comment_attributes(comment) def pull_request_comment_attributes(comment)
......
...@@ -4,82 +4,29 @@ module Gitlab ...@@ -4,82 +4,29 @@ module Gitlab
include Gitlab::Routing include Gitlab::Routing
include IconsHelper include IconsHelper
MissingResolution = Class.new(ResolutionError)
CONTEXT_LINES = 3 CONTEXT_LINES = 3
attr_reader :merge_file_result, :their_path, :our_path, :our_mode, :merge_request, :repository attr_reader :merge_request
def initialize(merge_file_result, conflict, merge_request:)
@merge_file_result = merge_file_result
@their_path = conflict[:theirs][:path]
@our_path = conflict[:ours][:path]
@our_mode = conflict[:ours][:mode]
@merge_request = merge_request
@repository = merge_request.project.repository
@match_line_headers = {}
end
def content
merge_file_result[:data]
end
def our_blob # 'raw' holds the Gitlab::Git::Conflict::File that this instance wraps
@our_blob ||= repository.blob_at(merge_request.diff_refs.head_sha, our_path) attr_reader :raw
end
def type delegate :type, :content, :their_path, :our_path, :our_mode, :our_blob, :repository, to: :raw
lines unless @type
@type.inquiry def initialize(raw, merge_request:)
@raw = raw
@merge_request = merge_request
@match_line_headers = {}
end end
# Array of Gitlab::Diff::Line objects
def lines def lines
return @lines if defined?(@lines) return @lines if defined?(@lines)
begin @lines = raw.lines.nil? ? nil : map_raw_lines(raw.lines)
@type = 'text'
@lines = Gitlab::Conflict::Parser.new.parse(content,
our_path: our_path,
their_path: their_path,
parent_file: self)
rescue Gitlab::Conflict::Parser::ParserError
@type = 'text-editor'
@lines = nil
end
end end
def resolve_lines(resolution) def resolve_lines(resolution)
section_id = nil map_raw_lines(raw.resolve_lines(resolution))
lines.map do |line|
unless line.type
section_id = nil
next line
end
section_id ||= line_code(line)
case resolution[section_id]
when 'head'
next unless line.type == 'new'
when 'origin'
next unless line.type == 'old'
else
raise MissingResolution, "Missing resolution for section ID: #{section_id}"
end
line
end.compact
end
def resolve_content(resolution)
if resolution == content
raise MissingResolution, "Resolved content has no changes for file #{our_path}"
end
resolution
end end
def highlight_lines! def highlight_lines!
...@@ -163,7 +110,7 @@ module Gitlab ...@@ -163,7 +110,7 @@ module Gitlab
end end
def line_code(line) def line_code(line)
Gitlab::Diff::LineCode.generate(our_path, line.new_pos, line.old_pos) Gitlab::Git.diff_line_code(our_path, line.new_pos, line.old_pos)
end end
def create_match_line(line) def create_match_line(line)
...@@ -227,15 +174,14 @@ module Gitlab ...@@ -227,15 +174,14 @@ module Gitlab
new_path: our_path) new_path: our_path)
end end
# Don't try to print merge_request or repository. private
def inspect
instance_variables = [:merge_file_result, :their_path, :our_path, :our_mode, :type].map do |instance_variable|
value = instance_variable_get("@#{instance_variable}")
"#{instance_variable}=\"#{value}\"" def map_raw_lines(raw_lines)
raw_lines.map do |raw_line|
Gitlab::Diff::Line.new(raw_line[:full_line], raw_line[:type],
raw_line[:line_obj_index], raw_line[:line_old],
raw_line[:line_new], parent_file: self)
end end
"#<#{self.class} #{instance_variables.join(' ')}>"
end end
end end
end end
......
module Gitlab module Gitlab
module Conflict module Conflict
class FileCollection class FileCollection
ConflictSideMissing = Class.new(StandardError) attr_reader :merge_request, :resolver
attr_reader :merge_request, :our_commit, :their_commit, :project def initialize(merge_request)
source_repo = merge_request.source_project.repository.raw
delegate :repository, to: :project our_commit = merge_request.source_branch_head.raw
their_commit = merge_request.target_branch_head.raw
class << self target_repo = merge_request.target_project.repository.raw
# We can only write when getting the merge index from the source @resolver = Gitlab::Git::Conflict::Resolver.new(source_repo, our_commit, target_repo, their_commit)
# project, because we will write to that project. We don't use this all @merge_request = merge_request
# the time because this fetches a ref into the source project, which
# isn't needed for reading.
def for_resolution(merge_request)
project = merge_request.source_project
new(merge_request, project).tap do |file_collection|
project
.repository
.with_repo_branch_commit(merge_request.target_project.repository.raw_repository, merge_request.target_branch) do
yield file_collection
end
end
end
# We don't need to do `with_repo_branch_commit` here, because the target
# project always fetches source refs when creating merge request diffs.
def read_only(merge_request)
new(merge_request, merge_request.target_project)
end
end end
def merge_index def resolve(user, commit_message, files)
@merge_index ||= repository.rugged.merge_commits(our_commit, their_commit) args = {
source_branch: merge_request.source_branch,
target_branch: merge_request.target_branch,
commit_message: commit_message || default_commit_message
}
resolver.resolve_conflicts(user, files, args)
end end
def files def files
@files ||= merge_index.conflicts.map do |conflict| @files ||= resolver.conflicts.map do |conflict_file|
raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours] Gitlab::Conflict::File.new(conflict_file, merge_request: merge_request)
Gitlab::Conflict::File.new(merge_index.merge_file(conflict[:ours][:path]),
conflict,
merge_request: merge_request)
end end
end end
...@@ -61,8 +42,8 @@ module Gitlab ...@@ -61,8 +42,8 @@ module Gitlab
end end
def default_commit_message def default_commit_message
conflict_filenames = merge_index.conflicts.map do |conflict| conflict_filenames = files.map do |conflict|
"# #{conflict[:ours][:path]}" "# #{conflict.our_path}"
end end
<<EOM.chomp <<EOM.chomp
...@@ -72,15 +53,6 @@ Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branc ...@@ -72,15 +53,6 @@ Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branc
#{conflict_filenames.join("\n")} #{conflict_filenames.join("\n")}
EOM EOM
end end
private
def initialize(merge_request, project)
@merge_request = merge_request
@our_commit = merge_request.source_branch_head.raw.rugged_commit
@their_commit = merge_request.target_branch_head.raw.rugged_commit
@project = project
end
end end
end end
end end
module Gitlab
module Conflict
class Parser
UnresolvableError = Class.new(StandardError)
UnmergeableFile = Class.new(UnresolvableError)
UnsupportedEncoding = Class.new(UnresolvableError)
# Recoverable errors - the conflict can be resolved in an editor, but not with
# sections.
ParserError = Class.new(StandardError)
UnexpectedDelimiter = Class.new(ParserError)
MissingEndDelimiter = Class.new(ParserError)
def parse(text, our_path:, their_path:, parent_file: nil)
validate_text!(text)
line_obj_index = 0
line_old = 1
line_new = 1
type = nil
lines = []
conflict_start = "<<<<<<< #{our_path}"
conflict_middle = '======='
conflict_end = ">>>>>>> #{their_path}"
text.each_line.map do |line|
full_line = line.delete("\n")
if full_line == conflict_start
validate_delimiter!(type.nil?)
type = 'new'
elsif full_line == conflict_middle
validate_delimiter!(type == 'new')
type = 'old'
elsif full_line == conflict_end
validate_delimiter!(type == 'old')
type = nil
elsif line[0] == '\\'
type = 'nonewline'
lines << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, parent_file: parent_file)
else
lines << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, parent_file: parent_file)
line_old += 1 if type != 'new'
line_new += 1 if type != 'old'
line_obj_index += 1
end
end
raise MissingEndDelimiter unless type.nil?
lines
end
private
def validate_text!(text)
raise UnmergeableFile if text.blank? # Typically a binary file
raise UnmergeableFile if text.length > 200.kilobytes
text.force_encoding('UTF-8')
raise UnsupportedEncoding unless text.valid_encoding?
end
def validate_delimiter!(condition)
raise UnexpectedDelimiter unless condition
end
end
end
end
module Gitlab
module Conflict
ResolutionError = Class.new(StandardError)
end
end
...@@ -49,7 +49,7 @@ module Gitlab ...@@ -49,7 +49,7 @@ module Gitlab
def line_code(line) def line_code(line)
return if line.meta? return if line.meta?
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) Gitlab::Git.diff_line_code(file_path, line.new_pos, line.old_pos)
end end
def line_for_line_code(code) def line_for_line_code(code)
......
module Gitlab
module Diff
class LineCode
def self.generate(file_path, new_line_position, old_line_position)
"#{Digest::SHA1.hexdigest(file_path)}_#{old_line_position}_#{new_line_position}"
end
end
end
end
...@@ -66,6 +66,10 @@ module Gitlab ...@@ -66,6 +66,10 @@ module Gitlab
end end
end end
end end
def diff_line_code(file_path, new_line_position, old_line_position)
"#{Digest::SHA1.hexdigest(file_path)}_#{old_line_position}_#{new_line_position}"
end
end end
end end
end end
module Gitlab
module Git
module Conflict
class File
attr_reader :content, :their_path, :our_path, :our_mode, :repository
def initialize(repository, commit_oid, conflict, content)
@repository = repository
@commit_oid = commit_oid
@their_path = conflict[:theirs][:path]
@our_path = conflict[:ours][:path]
@our_mode = conflict[:ours][:mode]
@content = content
end
def lines
return @lines if defined?(@lines)
begin
@type = 'text'
@lines = Gitlab::Git::Conflict::Parser.parse(content,
our_path: our_path,
their_path: their_path)
rescue Gitlab::Git::Conflict::Parser::ParserError
@type = 'text-editor'
@lines = nil
end
end
def type
lines unless @type
@type.inquiry
end
def our_blob
# REFACTOR NOTE: the source of `commit_oid` used to be
# `merge_request.diff_refs.head_sha`. Instead of passing this value
# around the new lib structure, I decided to use `@commit_oid` which is
# equivalent to `merge_request.source_branch_head.raw.rugged_commit.oid`.
# That is what `merge_request.diff_refs.head_sha` is equivalent to when
# `merge_request` is not persisted (see `MergeRequest#diff_head_commit`).
# I think using the same oid is more consistent anyways, but if Conflicts
# start breaking, the change described above is a good place to look at.
@our_blob ||= repository.blob_at(@commit_oid, our_path)
end
def line_code(line)
Gitlab::Git.diff_line_code(our_path, line[:line_new], line[:line_old])
end
def resolve_lines(resolution)
section_id = nil
lines.map do |line|
unless line[:type]
section_id = nil
next line
end
section_id ||= line_code(line)
case resolution[section_id]
when 'head'
next unless line[:type] == 'new'
when 'origin'
next unless line[:type] == 'old'
else
raise Gitlab::Git::Conflict::Resolver::ResolutionError, "Missing resolution for section ID: #{section_id}"
end
line
end.compact
end
def resolve_content(resolution)
if resolution == content
raise Gitlab::Git::Conflict::Resolver::ResolutionError, "Resolved content has no changes for file #{our_path}"
end
resolution
end
end
end
end
end
module Gitlab
module Git
module Conflict
class Parser
UnresolvableError = Class.new(StandardError)
UnmergeableFile = Class.new(UnresolvableError)
UnsupportedEncoding = Class.new(UnresolvableError)
# Recoverable errors - the conflict can be resolved in an editor, but not with
# sections.
ParserError = Class.new(StandardError)
UnexpectedDelimiter = Class.new(ParserError)
MissingEndDelimiter = Class.new(ParserError)
class << self
def parse(text, our_path:, their_path:, parent_file: nil)
validate_text!(text)
line_obj_index = 0
line_old = 1
line_new = 1
type = nil
lines = []
conflict_start = "<<<<<<< #{our_path}"
conflict_middle = '======='
conflict_end = ">>>>>>> #{their_path}"
text.each_line.map do |line|
full_line = line.delete("\n")
if full_line == conflict_start
validate_delimiter!(type.nil?)
type = 'new'
elsif full_line == conflict_middle
validate_delimiter!(type == 'new')
type = 'old'
elsif full_line == conflict_end
validate_delimiter!(type == 'old')
type = nil
elsif line[0] == '\\'
type = 'nonewline'
lines << {
full_line: full_line,
type: type,
line_obj_index: line_obj_index,
line_old: line_old,
line_new: line_new
}
else
lines << {
full_line: full_line,
type: type,
line_obj_index: line_obj_index,
line_old: line_old,
line_new: line_new
}
line_old += 1 if type != 'new'
line_new += 1 if type != 'old'
line_obj_index += 1
end
end
raise MissingEndDelimiter unless type.nil?
lines
end
private
def validate_text!(text)
raise UnmergeableFile if text.blank? # Typically a binary file
raise UnmergeableFile if text.length > 200.kilobytes
text.force_encoding('UTF-8')
raise UnsupportedEncoding unless text.valid_encoding?
end
def validate_delimiter!(condition)
raise UnexpectedDelimiter unless condition
end
end
end
end
end
end
module Gitlab
module Git
module Conflict
class Resolver
ConflictSideMissing = Class.new(StandardError)
ResolutionError = Class.new(StandardError)
def initialize(repository, our_commit, target_repository, their_commit)
@repository = repository
@our_commit = our_commit.rugged_commit
@target_repository = target_repository
@their_commit = their_commit.rugged_commit
end
def conflicts
@conflicts ||= begin
target_index = @target_repository.rugged.merge_commits(@our_commit, @their_commit)
# We don't need to do `with_repo_branch_commit` here, because the target
# project always fetches source refs when creating merge request diffs.
target_index.conflicts.map do |conflict|
raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours]
Gitlab::Git::Conflict::File.new(
@target_repository,
@our_commit.oid,
conflict,
target_index.merge_file(conflict[:ours][:path])[:data]
)
end
end
end
def resolve_conflicts(user, files, source_branch:, target_branch:, commit_message:)
@repository.with_repo_branch_commit(@target_repository, target_branch) do
files.each do |file_params|
conflict_file = conflict_for_path(file_params[:old_path], file_params[:new_path])
write_resolved_file_to_index(conflict_file, file_params)
end
unless index.conflicts.empty?
missing_files = index.conflicts.map { |file| file[:ours][:path] }
raise ResolutionError, "Missing resolutions for the following files: #{missing_files.join(', ')}"
end
commit_params = {
message: commit_message,
parents: [@our_commit, @their_commit].map(&:oid)
}
@repository.commit_index(user, source_branch, index, commit_params)
end
end
def conflict_for_path(old_path, new_path)
conflicts.find do |conflict|
conflict.their_path == old_path && conflict.our_path == new_path
end
end
private
# We can only write when getting the merge index from the source
# project, because we will write to that project. We don't use this all
# the time because this fetches a ref into the source project, which
# isn't needed for reading.
def index
@index ||= @repository.rugged.merge_commits(@our_commit, @their_commit)
end
def write_resolved_file_to_index(file, params)
if params[:sections]
resolved_lines = file.resolve_lines(params[:sections])
new_file = resolved_lines.map { |line| line[:full_line] }.join("\n")
new_file << "\n" if file.our_blob.data.ends_with?("\n")
elsif params[:content]
new_file = file.resolve_content(params[:content])
end
our_path = file.our_path
index.add(path: our_path, oid: @repository.rugged.write(new_file, :blob), mode: file.our_mode)
index.conflict_remove(our_path)
end
end
end
end
end
...@@ -1109,6 +1109,24 @@ module Gitlab ...@@ -1109,6 +1109,24 @@ module Gitlab
popen(args, @path).last.zero? popen(args, @path).last.zero?
end end
def blob_at(sha, path)
Gitlab::Git::Blob.find(self, sha, path) unless Gitlab::Git.blank_ref?(sha)
end
def commit_index(user, branch_name, index, options)
committer = user_to_committer(user)
OperationService.new(user, self).with_branch(branch_name) do
commit_params = options.merge(
tree: index.write_tree(rugged),
author: committer,
committer: committer
)
create_commit(commit_params)
end
end
def gitaly_repository def gitaly_repository
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository) Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository)
end end
......
...@@ -38,7 +38,7 @@ module Gitlab ...@@ -38,7 +38,7 @@ module Gitlab
end end
def generate_line_code(line) def generate_line_code(line)
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) Gitlab::Git.diff_line_code(file_path, line.new_pos, line.old_pos)
end end
def on_diff? def on_diff?
......
...@@ -17,8 +17,8 @@ describe Projects::MergeRequests::ConflictsController do ...@@ -17,8 +17,8 @@ describe Projects::MergeRequests::ConflictsController do
describe 'GET show' do describe 'GET show' do
context 'when the conflicts cannot be resolved in the UI' do context 'when the conflicts cannot be resolved in the UI' do
before do before do
allow_any_instance_of(Gitlab::Conflict::Parser) allow(Gitlab::Git::Conflict::Parser).to receive(:parse)
.to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnmergeableFile) .and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
get :show, get :show,
namespace_id: merge_request_with_conflicts.project.namespace.to_param, namespace_id: merge_request_with_conflicts.project.namespace.to_param,
...@@ -109,8 +109,8 @@ describe Projects::MergeRequests::ConflictsController do ...@@ -109,8 +109,8 @@ describe Projects::MergeRequests::ConflictsController do
context 'when the conflicts cannot be resolved in the UI' do context 'when the conflicts cannot be resolved in the UI' do
before do before do
allow_any_instance_of(Gitlab::Conflict::Parser) allow(Gitlab::Git::Conflict::Parser).to receive(:parse)
.to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnmergeableFile) .and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
conflict_for_path('files/ruby/regex.rb') conflict_for_path('files/ruby/regex.rb')
end end
......
...@@ -2,7 +2,7 @@ require 'spec_helper' ...@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Conflict::FileCollection do describe Gitlab::Conflict::FileCollection do
let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start') } let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start') }
let(:file_collection) { described_class.read_only(merge_request) } let(:file_collection) { described_class.new(merge_request) }
describe '#files' do describe '#files' do
it 'returns an array of Conflict::Files' do it 'returns an array of Conflict::Files' do
......
...@@ -8,9 +8,10 @@ describe Gitlab::Conflict::File do ...@@ -8,9 +8,10 @@ describe Gitlab::Conflict::File do
let(:our_commit) { rugged.branches['conflict-resolvable'].target } let(:our_commit) { rugged.branches['conflict-resolvable'].target }
let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) } let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) }
let(:index) { rugged.merge_commits(our_commit, their_commit) } let(:index) { rugged.merge_commits(our_commit, their_commit) }
let(:conflict) { index.conflicts.last } let(:rugged_conflict) { index.conflicts.last }
let(:merge_file_result) { index.merge_file('files/ruby/regex.rb') } let(:raw_conflict_content) { index.merge_file('files/ruby/regex.rb')[:data] }
let(:conflict_file) { described_class.new(merge_file_result, conflict, merge_request: merge_request) } let(:raw_conflict_file) { Gitlab::Git::Conflict::File.new(repository, our_commit.oid, rugged_conflict, raw_conflict_content) }
let(:conflict_file) { described_class.new(raw_conflict_file, merge_request: merge_request) }
describe '#resolve_lines' do describe '#resolve_lines' do
let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact } let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact }
...@@ -48,18 +49,18 @@ describe Gitlab::Conflict::File do ...@@ -48,18 +49,18 @@ describe Gitlab::Conflict::File do
end end
end end
it 'raises MissingResolution when passed a hash without resolutions for all sections' do it 'raises ResolutionError when passed a hash without resolutions for all sections' do
empty_hash = section_keys.map { |key| [key, nil] }.to_h empty_hash = section_keys.map { |key| [key, nil] }.to_h
invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h
expect { conflict_file.resolve_lines({}) } expect { conflict_file.resolve_lines({}) }
.to raise_error(Gitlab::Conflict::File::MissingResolution) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
expect { conflict_file.resolve_lines(empty_hash) } expect { conflict_file.resolve_lines(empty_hash) }
.to raise_error(Gitlab::Conflict::File::MissingResolution) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
expect { conflict_file.resolve_lines(invalid_hash) } expect { conflict_file.resolve_lines(invalid_hash) }
.to raise_error(Gitlab::Conflict::File::MissingResolution) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
end end
end end
...@@ -144,7 +145,7 @@ describe Gitlab::Conflict::File do ...@@ -144,7 +145,7 @@ describe Gitlab::Conflict::File do
end end
context 'with an example file' do context 'with an example file' do
let(:file) do let(:raw_conflict_content) do
<<FILE <<FILE
# Ensure there is no match line header here # Ensure there is no match line header here
def username_regexp def username_regexp
...@@ -220,7 +221,6 @@ end ...@@ -220,7 +221,6 @@ end
FILE FILE
end end
let(:conflict_file) { described_class.new({ data: file }, conflict, merge_request: merge_request) }
let(:sections) { conflict_file.sections } let(:sections) { conflict_file.sections }
it 'sets the correct match line headers' do it 'sets the correct match line headers' do
......
...@@ -40,7 +40,7 @@ describe Gitlab::Diff::Position do ...@@ -40,7 +40,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 0) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 0)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -108,7 +108,7 @@ describe Gitlab::Diff::Position do ...@@ -108,7 +108,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 15) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 15)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -149,7 +149,7 @@ describe Gitlab::Diff::Position do ...@@ -149,7 +149,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -189,7 +189,7 @@ describe Gitlab::Diff::Position do ...@@ -189,7 +189,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 13, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, 13, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -233,7 +233,7 @@ describe Gitlab::Diff::Position do ...@@ -233,7 +233,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 5) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 5)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -274,7 +274,7 @@ describe Gitlab::Diff::Position do ...@@ -274,7 +274,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -314,7 +314,7 @@ describe Gitlab::Diff::Position do ...@@ -314,7 +314,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 4, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, 4, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -357,7 +357,7 @@ describe Gitlab::Diff::Position do ...@@ -357,7 +357,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 0, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, 0, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -399,7 +399,7 @@ describe Gitlab::Diff::Position do ...@@ -399,7 +399,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 0) line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 0)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
...@@ -447,7 +447,7 @@ describe Gitlab::Diff::Position do ...@@ -447,7 +447,7 @@ describe Gitlab::Diff::Position do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 0, subject.old_line) line_code = Gitlab::Git.diff_line_code(subject.file_path, 0, subject.old_line)
expect(subject.line_code(project.repository)).to eq(line_code) expect(subject.line_code(project.repository)).to eq(line_code)
end end
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::Conflict::Parser do describe Gitlab::Git::Conflict::Parser do
let(:parser) { described_class.new } describe '.parse' do
describe '#parse' do
def parse_text(text) def parse_text(text)
parser.parse(text, our_path: 'README.md', their_path: 'README.md') described_class.parse(text, our_path: 'README.md', their_path: 'README.md')
end end
context 'when the file has valid conflicts' do context 'when the file has valid conflicts' do
...@@ -87,33 +85,37 @@ CONFLICT ...@@ -87,33 +85,37 @@ CONFLICT
end end
let(:lines) do let(:lines) do
parser.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb') described_class.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb')
end
let(:old_line_numbers) do
lines.select { |line| line[:type] != 'new' }.map { |line| line[:line_old] }
end end
let(:new_line_numbers) do
lines.select { |line| line[:type] != 'old' }.map { |line| line[:line_new] }
end
let(:line_indexes) { lines.map { |line| line[:line_obj_index] } }
it 'sets our lines as new lines' do it 'sets our lines as new lines' do
expect(lines[8..13]).to all(have_attributes(type: 'new')) expect(lines[8..13]).to all(include(type: 'new'))
expect(lines[26..27]).to all(have_attributes(type: 'new')) expect(lines[26..27]).to all(include(type: 'new'))
expect(lines[56..57]).to all(have_attributes(type: 'new')) expect(lines[56..57]).to all(include(type: 'new'))
end end
it 'sets their lines as old lines' do it 'sets their lines as old lines' do
expect(lines[14..19]).to all(have_attributes(type: 'old')) expect(lines[14..19]).to all(include(type: 'old'))
expect(lines[28..29]).to all(have_attributes(type: 'old')) expect(lines[28..29]).to all(include(type: 'old'))
expect(lines[58..59]).to all(have_attributes(type: 'old')) expect(lines[58..59]).to all(include(type: 'old'))
end end
it 'sets non-conflicted lines as both' do it 'sets non-conflicted lines as both' do
expect(lines[0..7]).to all(have_attributes(type: nil)) expect(lines[0..7]).to all(include(type: nil))
expect(lines[20..25]).to all(have_attributes(type: nil)) expect(lines[20..25]).to all(include(type: nil))
expect(lines[30..55]).to all(have_attributes(type: nil)) expect(lines[30..55]).to all(include(type: nil))
expect(lines[60..62]).to all(have_attributes(type: nil)) expect(lines[60..62]).to all(include(type: nil))
end end
it 'sets consecutive line numbers for index, old_pos, and new_pos' do it 'sets consecutive line numbers for line_obj_index, line_old, and line_new' do
old_line_numbers = lines.select { |line| line.type != 'new' }.map(&:old_pos) expect(line_indexes).to eq(0.upto(62).to_a)
new_line_numbers = lines.select { |line| line.type != 'old' }.map(&:new_pos)
expect(lines.map(&:index)).to eq(0.upto(62).to_a)
expect(old_line_numbers).to eq(1.upto(53).to_a) expect(old_line_numbers).to eq(1.upto(53).to_a)
expect(new_line_numbers).to eq(1.upto(53).to_a) expect(new_line_numbers).to eq(1.upto(53).to_a)
end end
...@@ -123,12 +125,12 @@ CONFLICT ...@@ -123,12 +125,12 @@ CONFLICT
context 'when there is a non-start delimiter first' do context 'when there is a non-start delimiter first' do
it 'raises UnexpectedDelimiter when there is a middle delimiter first' do it 'raises UnexpectedDelimiter when there is a middle delimiter first' do
expect { parse_text('=======') } expect { parse_text('=======') }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'raises UnexpectedDelimiter when there is an end delimiter first' do it 'raises UnexpectedDelimiter when there is an end delimiter first' do
expect { parse_text('>>>>>>> README.md') } expect { parse_text('>>>>>>> README.md') }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'does not raise when there is an end delimiter for a different path first' do it 'does not raise when there is an end delimiter for a different path first' do
...@@ -143,12 +145,12 @@ CONFLICT ...@@ -143,12 +145,12 @@ CONFLICT
it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do
expect { parse_text(start_text + '>>>>>>> README.md' + end_text) } expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'raises UnexpectedDelimiter when it is followed by another start delimiter' do it 'raises UnexpectedDelimiter when it is followed by another start delimiter' do
expect { parse_text(start_text + start_text + end_text) } expect { parse_text(start_text + start_text + end_text) }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'does not raise when it is followed by a start delimiter for a different path' do it 'does not raise when it is followed by a start delimiter for a different path' do
...@@ -163,12 +165,12 @@ CONFLICT ...@@ -163,12 +165,12 @@ CONFLICT
it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do
expect { parse_text(start_text + '=======' + end_text) } expect { parse_text(start_text + '=======' + end_text) }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'raises UnexpectedDelimiter when it is followed by a start delimiter' do it 'raises UnexpectedDelimiter when it is followed by a start delimiter' do
expect { parse_text(start_text + start_text + end_text) } expect { parse_text(start_text + start_text + end_text) }
.to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
end end
it 'does not raise when it is followed by a start delimiter for another path' do it 'does not raise when it is followed by a start delimiter for another path' do
...@@ -181,25 +183,25 @@ CONFLICT ...@@ -181,25 +183,25 @@ CONFLICT
start_text = "<<<<<<< README.md\n=======\n" start_text = "<<<<<<< README.md\n=======\n"
expect { parse_text(start_text) } expect { parse_text(start_text) }
.to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter)
expect { parse_text(start_text + '>>>>>>> some-other-path.md') } expect { parse_text(start_text + '>>>>>>> some-other-path.md') }
.to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter) .to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter)
end end
end end
context 'other file types' do context 'other file types' do
it 'raises UnmergeableFile when lines is blank, indicating a binary file' do it 'raises UnmergeableFile when lines is blank, indicating a binary file' do
expect { parse_text('') } expect { parse_text('') }
.to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
expect { parse_text(nil) } expect { parse_text(nil) }
.to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
end end
it 'raises UnmergeableFile when the file is over 200 KB' do it 'raises UnmergeableFile when the file is over 200 KB' do
expect { parse_text('a' * 204801) } expect { parse_text('a' * 204801) }
.to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
end end
# All text from Rugged has an encoding of ASCII_8BIT, so force that in # All text from Rugged has an encoding of ASCII_8BIT, so force that in
...@@ -214,7 +216,7 @@ CONFLICT ...@@ -214,7 +216,7 @@ CONFLICT
context 'when the file contains non-UTF-8 characters' do context 'when the file contains non-UTF-8 characters' do
it 'raises UnsupportedEncoding' do it 'raises UnsupportedEncoding' do
expect { parse_text("a\xC4\xFC".force_encoding(Encoding::ASCII_8BIT)) } expect { parse_text("a\xC4\xFC".force_encoding(Encoding::ASCII_8BIT)) }
.to raise_error(Gitlab::Conflict::Parser::UnsupportedEncoding) .to raise_error(Gitlab::Git::Conflict::Parser::UnsupportedEncoding)
end end
end end
end end
......
...@@ -105,7 +105,7 @@ describe DiffNote do ...@@ -105,7 +105,7 @@ describe DiffNote do
describe "#line_code" do describe "#line_code" do
it "returns the correct line code" do it "returns the correct line code" do
line_code = Gitlab::Diff::LineCode.generate(position.file_path, position.formatter.new_line, 15) line_code = Gitlab::Git.diff_line_code(position.file_path, position.formatter.new_line, 15)
expect(subject.line_code).to eq(line_code) expect(subject.line_code).to eq(line_code)
end end
......
...@@ -35,7 +35,7 @@ describe MergeRequests::Conflicts::ListService do ...@@ -35,7 +35,7 @@ describe MergeRequests::Conflicts::ListService do
it 'returns a falsey value when the MR has a missing ref after a force push' do it 'returns a falsey value when the MR has a missing ref after a force push' do
merge_request = create_merge_request('conflict-resolvable') merge_request = create_merge_request('conflict-resolvable')
service = conflicts_service(merge_request) service = conflicts_service(merge_request)
allow(service.conflicts).to receive(:merge_index).and_raise(Rugged::OdbError) allow_any_instance_of(Rugged::Repository).to receive(:merge_commits).and_raise(Rugged::OdbError)
expect(service.can_be_resolved_in_ui?).to be_falsey expect(service.can_be_resolved_in_ui?).to be_falsey
end end
......
...@@ -107,25 +107,27 @@ describe MergeRequests::Conflicts::ResolveService do ...@@ -107,25 +107,27 @@ describe MergeRequests::Conflicts::ResolveService do
branch_name: 'conflict-start') branch_name: 'conflict-start')
end end
def resolve_conflicts subject do
described_class.new(merge_request_from_fork).execute(user, params) described_class.new(merge_request_from_fork).execute(user, params)
end end
it 'gets conflicts from the source project' do it 'gets conflicts from the source project' do
# REFACTOR NOTE: We used to test that `project.repository.rugged` wasn't
# used in this case, but since the refactor, for simplification,
# we always use that repository for read only operations.
expect(forked_project.repository.rugged).to receive(:merge_commits).and_call_original expect(forked_project.repository.rugged).to receive(:merge_commits).and_call_original
expect(project.repository.rugged).not_to receive(:merge_commits)
resolve_conflicts subject
end end
it 'creates a commit with the message' do it 'creates a commit with the message' do
resolve_conflicts subject
expect(merge_request_from_fork.source_branch_head.message).to eq(params[:commit_message]) expect(merge_request_from_fork.source_branch_head.message).to eq(params[:commit_message])
end end
it 'creates a commit with the correct parents' do it 'creates a commit with the correct parents' do
resolve_conflicts subject
expect(merge_request_from_fork.source_branch_head.parents.map(&:id)) expect(merge_request_from_fork.source_branch_head.parents.map(&:id))
.to eq(['404fa3fc7c2c9b5dacff102f353bdf55b1be2813', target_head]) .to eq(['404fa3fc7c2c9b5dacff102f353bdf55b1be2813', target_head])
...@@ -200,14 +202,19 @@ describe MergeRequests::Conflicts::ResolveService do ...@@ -200,14 +202,19 @@ describe MergeRequests::Conflicts::ResolveService do
} }
end end
it 'raises a MissingResolution error' do it 'raises a ResolutionError error' do
expect { service.execute(user, invalid_params) } expect { service.execute(user, invalid_params) }
.to raise_error(Gitlab::Conflict::File::MissingResolution) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
end end
end end
context 'when the content of a file is unchanged' do context 'when the content of a file is unchanged' do
let(:list_service) { MergeRequests::Conflicts::ListService.new(merge_request) } let(:resolver) do
MergeRequests::Conflicts::ListService.new(merge_request).conflicts.resolver
end
let(:regex_conflict) do
resolver.conflict_for_path('files/ruby/regex.rb', 'files/ruby/regex.rb')
end
let(:invalid_params) do let(:invalid_params) do
{ {
...@@ -219,16 +226,16 @@ describe MergeRequests::Conflicts::ResolveService do ...@@ -219,16 +226,16 @@ describe MergeRequests::Conflicts::ResolveService do
}, { }, {
old_path: 'files/ruby/regex.rb', old_path: 'files/ruby/regex.rb',
new_path: 'files/ruby/regex.rb', new_path: 'files/ruby/regex.rb',
content: list_service.conflicts.file_for_path('files/ruby/regex.rb', 'files/ruby/regex.rb').content content: regex_conflict.content
} }
], ],
commit_message: 'This is a commit message!' commit_message: 'This is a commit message!'
} }
end end
it 'raises a MissingResolution error' do it 'raises a ResolutionError error' do
expect { service.execute(user, invalid_params) } expect { service.execute(user, invalid_params) }
.to raise_error(Gitlab::Conflict::File::MissingResolution) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
end end
end end
...@@ -246,9 +253,9 @@ describe MergeRequests::Conflicts::ResolveService do ...@@ -246,9 +253,9 @@ describe MergeRequests::Conflicts::ResolveService do
} }
end end
it 'raises a MissingFiles error' do it 'raises a ResolutionError error' do
expect { service.execute(user, invalid_params) } expect { service.execute(user, invalid_params) }
.to raise_error(described_class::MissingFiles) .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
end end
end end
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册