diff options
author | Alejandro RodrÃguez <alejorro70@gmail.com> | 2017-10-06 02:22:24 +0300 |
---|---|---|
committer | Alejandro RodrÃguez <alejorro70@gmail.com> | 2017-10-13 03:45:15 +0300 |
commit | 9fda629a347cb43d8f5871f101192187fcdeeea2 (patch) | |
tree | 05e0129a812061d049da8ce72450e9c9997738f7 /lib/gitlab/conflict | |
parent | e49e443b70fc819bf19866523f08ef0707e1b5a4 (diff) |
Encapsulate git operations for conflict resolution into lib
Diffstat (limited to 'lib/gitlab/conflict')
-rw-r--r-- | lib/gitlab/conflict/file_collection.rb | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb index 90f83e0f810..4fedfe8691a 100644 --- a/lib/gitlab/conflict/file_collection.rb +++ b/lib/gitlab/conflict/file_collection.rb @@ -2,8 +2,9 @@ module Gitlab module Conflict class FileCollection ConflictSideMissing = Class.new(StandardError) + MissingFiles = Class.new(ResolutionError) - attr_reader :merge_request, :our_commit, :their_commit, :project + attr_reader :merge_request, :our_commit, :their_commit, :project, :read_only delegate :repository, to: :project @@ -13,22 +14,41 @@ module Gitlab # 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 + new(merge_request, merge_request.source_project, false) 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) + new(merge_request, merge_request.target_project, true) + end + end + + def resolve(user, commit_message, files) + raise "can't resolve a read-only Conflict File Collection" if read_only + + repository.with_repo_branch_commit(merge_request.target_project.repository.raw, merge_request.target_branch) do + rugged = repository.rugged + + files.each do |file_params| + conflict_file = 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: commit_message || default_commit_message, + parents: [our_commit, their_commit].map(&:oid), + tree: merge_index.write_tree(rugged) + } + + repository.resolve_conflicts(user, merge_request.source_branch, commit_params) end end @@ -75,11 +95,27 @@ EOM private - def initialize(merge_request, project) + 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) + merge_index.conflict_remove(our_path) + end + + def initialize(merge_request, project, read_only) @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 + @read_only = read_only end end end |