2016-07-27 07:42:18 -04:00
|
|
|
module Gitlab
|
|
|
|
module Conflict
|
|
|
|
class FileCollection
|
2016-08-01 09:52:53 -04:00
|
|
|
class ConflictSideMissing < StandardError
|
|
|
|
end
|
|
|
|
|
2016-07-27 07:42:18 -04:00
|
|
|
attr_reader :merge_request, :our_commit, :their_commit
|
|
|
|
|
|
|
|
def initialize(merge_request)
|
|
|
|
@merge_request = merge_request
|
2016-07-29 06:05:33 -04:00
|
|
|
@our_commit = merge_request.source_branch_head.raw.raw_commit
|
2016-07-27 07:42:18 -04:00
|
|
|
@their_commit = merge_request.target_branch_head.raw.raw_commit
|
|
|
|
end
|
|
|
|
|
|
|
|
def repository
|
|
|
|
merge_request.project.repository
|
|
|
|
end
|
|
|
|
|
|
|
|
def merge_index
|
|
|
|
@merge_index ||= repository.rugged.merge_commits(our_commit, their_commit)
|
|
|
|
end
|
|
|
|
|
2016-08-02 08:56:50 -04:00
|
|
|
def resolve_conflicts!(params, user:)
|
|
|
|
resolutions = params[:sections]
|
|
|
|
commit_message = params[:commit_message] || default_commit_message
|
2016-07-27 12:54:04 -04:00
|
|
|
rugged = repository.rugged
|
|
|
|
committer = repository.user_to_committer(user)
|
|
|
|
|
|
|
|
files.each do |file|
|
|
|
|
file.resolve!(resolutions, index: merge_index, rugged: rugged)
|
|
|
|
end
|
|
|
|
|
|
|
|
new_tree = merge_index.write_tree(rugged)
|
|
|
|
|
|
|
|
Rugged::Commit.create(rugged,
|
|
|
|
author: committer,
|
|
|
|
committer: committer,
|
|
|
|
tree: new_tree,
|
|
|
|
message: commit_message,
|
2016-07-29 09:49:48 -04:00
|
|
|
parents: [our_commit, their_commit].map(&:oid),
|
2016-07-27 12:54:04 -04:00
|
|
|
update_ref: Gitlab::Git::BRANCH_REF_PREFIX + merge_request.source_branch)
|
|
|
|
end
|
|
|
|
|
2016-07-27 07:42:18 -04:00
|
|
|
def files
|
|
|
|
@files ||= merge_index.conflicts.map do |conflict|
|
2016-08-01 09:52:53 -04:00
|
|
|
raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours]
|
2016-07-27 07:42:18 -04:00
|
|
|
|
2016-08-01 09:52:53 -04:00
|
|
|
Gitlab::Conflict::File.new(merge_index.merge_file(conflict[:ours][:path]),
|
2016-07-27 07:42:18 -04:00
|
|
|
conflict,
|
|
|
|
repository: repository)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def as_json(opts = nil)
|
|
|
|
{
|
|
|
|
target_branch: merge_request.target_branch,
|
|
|
|
source_branch: merge_request.source_branch,
|
|
|
|
commit_sha: merge_request.diff_head_sha,
|
|
|
|
commit_message: default_commit_message,
|
|
|
|
files: files
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def default_commit_message
|
|
|
|
conflict_filenames = merge_index.conflicts.map do |conflict|
|
|
|
|
"# #{conflict[:ours][:path]}"
|
|
|
|
end
|
|
|
|
|
|
|
|
<<EOM.chomp
|
|
|
|
Merge branch '#{merge_request.source_branch}' into '#{merge_request.target_branch}'
|
|
|
|
|
|
|
|
# Conflicts:
|
|
|
|
#{conflict_filenames.join("\n")}
|
|
|
|
EOM
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|