diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-15 12:09:18 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-15 12:09:18 +0000 |
commit | b7c735c8ac11b8182807070fc6f84f2606e15427 (patch) | |
tree | e74b4d25abb8bbf23546f001dd94515e2840a3a3 /app/services | |
parent | 221b529789f4090341a825695aeb49b8df6dd11d (diff) | |
download | gitlab-ce-b7c735c8ac11b8182807070fc6f84f2606e15427.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services')
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) |