summaryrefslogtreecommitdiff
path: root/app/services
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-15 12:09:18 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-15 12:09:18 +0000
commitb7c735c8ac11b8182807070fc6f84f2606e15427 (patch)
treee74b4d25abb8bbf23546f001dd94515e2840a3a3 /app/services
parent221b529789f4090341a825695aeb49b8df6dd11d (diff)
downloadgitlab-ce-b7c735c8ac11b8182807070fc6f84f2606e15427.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services')
-rw-r--r--app/services/discussions/capture_diff_note_position_service.rb65
-rw-r--r--app/services/discussions/capture_diff_note_positions_service.rb34
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb7
-rw-r--r--app/services/notes/create_service.rb4
4 files changed, 110 insertions, 0 deletions
diff --git a/app/services/discussions/capture_diff_note_position_service.rb b/app/services/discussions/capture_diff_note_position_service.rb
new file mode 100644
index 00000000000..273a60f7e55
--- /dev/null
+++ b/app/services/discussions/capture_diff_note_position_service.rb
@@ -0,0 +1,65 @@
+# 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]
+
+ # 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: position.line_code(project.repository))
+ 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, base_sha = merge_ref_head.parent_ids
+ new_diff_refs = Gitlab::Diff::DiffRefs.new(
+ base_sha: base_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
diff --git a/app/services/discussions/capture_diff_note_positions_service.rb b/app/services/discussions/capture_diff_note_positions_service.rb
new file mode 100644
index 00000000000..3684a3f679a
--- /dev/null
+++ b/app/services/discussions/capture_diff_note_positions_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Discussions
+ class CaptureDiffNotePositionsService
+ def initialize(merge_request)
+ @merge_request = merge_request
+ end
+
+ def execute
+ return unless merge_request.has_complete_diff_refs?
+
+ discussions, paths = build_discussions
+
+ service = Discussions::CaptureDiffNotePositionService.new(merge_request, paths)
+
+ discussions.each do |discussion|
+ service.execute(discussion)
+ end
+ end
+
+ private
+
+ attr_reader :merge_request
+
+ def build_discussions
+ active_diff_discussions = merge_request.notes.new_diff_notes.discussions.select do |discussion|
+ discussion.active?(merge_request.diff_refs)
+ end
+ paths = active_diff_discussions.flat_map { |n| n.diff_file.paths }
+
+ [active_diff_discussions, paths]
+ end
+ end
+end
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 5b79e4d01f2..d3d661a3b75 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -118,11 +118,18 @@ module MergeRequests
if can_git_merge? && merge_to_ref
merge_request.mark_as_mergeable
+ update_diff_discussion_positions!
else
merge_request.mark_as_unmergeable
end
end
+ def update_diff_discussion_positions!
+ return if Feature.disabled?(:merge_ref_head_comments, merge_request.target_project)
+
+ Discussions::CaptureDiffNotePositionsService.new(merge_request).execute
+ end
+
def recheck!
if !merge_request.recheck_merge_status? && outdated_merge_ref?
merge_request.mark_as_unchecked
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 80bc4485988..6c1f52ec866 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -65,6 +65,10 @@ module Notes
if Feature.enabled?(:notes_create_service_tracking, project)
Gitlab::Tracking.event('Notes::CreateService', 'execute', tracking_data_for(note))
end
+
+ if Feature.enabled?(:merge_ref_head_comments, project) && note.for_merge_request? && note.diff_note? && note.start_of_discussion?
+ Discussions::CaptureDiffNotePositionService.new(note.noteable, note.diff_file&.paths).execute(note.discussion)
+ end
end
def do_commands(note, update_params, message, only_commands)