summaryrefslogtreecommitdiff
path: root/lib/gitlab/conflict
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2016-07-27 17:54:04 +0100
committerFatih Acet <acetfatih@gmail.com>2016-08-12 23:24:43 +0300
commit14a4b17d1c8a43c77b0459fd543be36838031610 (patch)
treed47104567085d3d711976eb299875f5e1aab0d24 /lib/gitlab/conflict
parenta1c79612172ce07c7b0de4c01fba8fa7369c71de (diff)
downloadgitlab-ce-14a4b17d1c8a43c77b0459fd543be36838031610.tar.gz
Allow resolving conflicts in MR controller
Diffstat (limited to 'lib/gitlab/conflict')
-rw-r--r--lib/gitlab/conflict/file.rb44
-rw-r--r--lib/gitlab/conflict/file_collection.rb20
2 files changed, 63 insertions, 1 deletions
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 7f81c72431d..80f6f7feecf 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -1,6 +1,9 @@
module Gitlab
module Conflict
class File
+ class MissingResolution < StandardError
+ end
+
CONTEXT_LINES = 3
attr_reader :merge_file_result, :their_path, :their_ref, :our_path, :our_ref, :repository
@@ -21,6 +24,39 @@ module Gitlab
their_path: their_path)
end
+ def resolve!(resolution, index:, rugged:)
+ new_file = resolve_lines(resolution).map(&:text).join("\n")
+
+ oid = rugged.write(new_file, :blob)
+ our_mode = index.conflict_get(our_path)[:ours][:mode]
+ index.add(path: our_path, oid: oid, mode: our_mode)
+ index.conflict_remove(our_path)
+ end
+
+ def resolve_lines(resolution)
+ current_section = nil
+
+ lines.map do |line|
+ unless line.type
+ current_section = nil
+ next line
+ end
+
+ current_section ||= resolution[line_code(line)]
+
+ case current_section
+ when 'ours'
+ next unless line.type == 'new'
+ when 'theirs'
+ next unless line.type == 'old'
+ else
+ raise MissingResolution
+ end
+
+ line
+ end.compact
+ end
+
def highlighted_lines
return @highlighted_lines if @highlighted_lines
@@ -77,10 +113,16 @@ module Gitlab
match_line.text = "@@ -#{match_line.old_pos},#{lines.last.old_pos} +#{match_line.new_pos},#{lines.last.new_pos} @@"
end
- section || { conflict: !no_conflict, lines: lines }
+ section ||= { conflict: !no_conflict, lines: lines }
+ section[:id] = line_code(lines.first) unless no_conflict
+ section
end
end
+ def line_code(line)
+ Gitlab::Diff::LineCode.generate(our_path, line.new_pos, line.old_pos)
+ end
+
def as_json(opts = nil)
{
old_path: their_path,
diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb
index a3035a5c3e6..a4a1505bb7d 100644
--- a/lib/gitlab/conflict/file_collection.rb
+++ b/lib/gitlab/conflict/file_collection.rb
@@ -17,6 +17,26 @@ module Gitlab
@merge_index ||= repository.rugged.merge_commits(our_commit, their_commit)
end
+ def resolve_conflicts!(resolutions, commit_message, user:)
+ rugged = repository.rugged
+ committer = repository.user_to_committer(user)
+ commit_message ||= default_commit_message
+
+ 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,
+ parents: [our_commit, their_commit],
+ update_ref: Gitlab::Git::BRANCH_REF_PREFIX + merge_request.source_branch)
+ end
+
def files
@files ||= merge_index.conflicts.map do |conflict|
their_path = conflict[:theirs][:path]