69 lines
1.9 KiB
Ruby
69 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Discussions
|
|
class CaptureDiffNotePositionService
|
|
def initialize(merge_request, paths)
|
|
@project = merge_request.project
|
|
@tracer = build_tracer(merge_request, paths)
|
|
end
|
|
|
|
def execute(discussion)
|
|
# The service has been implemented for text only
|
|
# The impact of image notes on this service is being investigated in
|
|
# https://gitlab.com/gitlab-org/gitlab/-/issues/213989
|
|
return unless discussion.on_text?
|
|
|
|
result = tracer&.trace(discussion.position)
|
|
return unless result
|
|
|
|
position = result[:position]
|
|
return unless position
|
|
|
|
line_code = position.line_code(project.repository)
|
|
return unless line_code
|
|
|
|
# Currently position data is copied across all notes of a discussion
|
|
# It makes sense to store a position only for the first note instead
|
|
# Within the newly introduced table we can start doing just that
|
|
DiffNotePosition.create_or_update_for(discussion.notes.first,
|
|
diff_type: :head,
|
|
position: position,
|
|
line_code: line_code)
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :tracer, :project
|
|
|
|
def build_tracer(merge_request, paths)
|
|
return if paths.blank?
|
|
|
|
old_diff_refs, new_diff_refs = build_diff_refs(merge_request)
|
|
|
|
return unless old_diff_refs && new_diff_refs
|
|
|
|
Gitlab::Diff::PositionTracer.new(
|
|
project: project,
|
|
old_diff_refs: old_diff_refs,
|
|
new_diff_refs: new_diff_refs,
|
|
paths: paths.uniq)
|
|
end
|
|
|
|
def build_diff_refs(merge_request)
|
|
merge_ref_head = merge_request.merge_ref_head
|
|
return unless merge_ref_head
|
|
|
|
start_sha, _ = merge_ref_head.parent_ids
|
|
new_diff_refs = Gitlab::Diff::DiffRefs.new(
|
|
base_sha: start_sha,
|
|
start_sha: start_sha,
|
|
head_sha: merge_ref_head.id)
|
|
|
|
old_diff_refs = merge_request.diff_refs
|
|
|
|
return if new_diff_refs == old_diff_refs
|
|
|
|
[old_diff_refs, new_diff_refs]
|
|
end
|
|
end
|
|
end
|