mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-15 21:39:00 +00:00
Fix conflict resolution from corrupted upstream
I don't know why this happens exactly, but given an upstream and fork repository from a customer, both of which required GC, resolving conflicts would corrupt the fork so badly that it couldn't be cloned. This isn't a perfect fix for that case, because the MR may still need to be merged manually, but it does ensure that the repository is at least usable. My best guess is that when we generate the index for the conflict resolution (which we previously did in the target project), we obtain a reference to an OID that doesn't exist in the source, even though we already fetch the refs from the target into the source. Explicitly setting the source project as the place to get the merge index from seems to prevent repository corruption in this way.
This commit is contained in:
@ -3,16 +3,33 @@ module Gitlab
|
||||
class FileCollection
|
||||
ConflictSideMissing = Class.new(StandardError)
|
||||
|
||||
attr_reader :merge_request, :our_commit, :their_commit
|
||||
attr_reader :merge_request, :our_commit, :their_commit, :project
|
||||
|
||||
def initialize(merge_request)
|
||||
@merge_request = merge_request
|
||||
@our_commit = merge_request.source_branch_head.raw.raw_commit
|
||||
@their_commit = merge_request.target_branch_head.raw.raw_commit
|
||||
end
|
||||
delegate :repository, to: :project
|
||||
|
||||
def repository
|
||||
merge_request.project.repository
|
||||
class << self
|
||||
# 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 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, 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
|
||||
|
||||
def merge_index
|
||||
@ -55,6 +72,15 @@ Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branc
|
||||
#{conflict_filenames.join("\n")}
|
||||
EOM
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def initialize(merge_request, project)
|
||||
@merge_request = merge_request
|
||||
@our_commit = merge_request.source_branch_head.raw.raw_commit
|
||||
@their_commit = merge_request.target_branch_head.raw.raw_commit
|
||||
@project = project
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user