summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/position_tracer.rb
blob: a1c82ce9afc4e0536bdcb3adf7ca37a2b4c2aae4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# frozen_string_literal: true

# Finds the diff position in the new diff that corresponds to the same location
# specified by the provided position in the old diff.
module Gitlab
  module Diff
    class PositionTracer
      attr_accessor :project
      attr_accessor :old_diff_refs
      attr_accessor :new_diff_refs
      attr_accessor :paths

      def initialize(project:, old_diff_refs:, new_diff_refs:, paths: nil)
        @project = project
        @old_diff_refs = old_diff_refs
        @new_diff_refs = new_diff_refs
        @paths = paths
      end

      def trace(old_position)
        return unless old_diff_refs&.complete? && new_diff_refs&.complete?
        return unless old_position.diff_refs == old_diff_refs

        strategy = old_position.on_text? ? LineStrategy : ImageStrategy

        strategy.new(self).trace(old_position)
      end

      def ac_diffs
        @ac_diffs ||= compare(
          old_diff_refs.base_sha || old_diff_refs.start_sha,
          new_diff_refs.base_sha || new_diff_refs.start_sha,
          straight: true
        )
      end

      def bd_diffs
        @bd_diffs ||= compare(old_diff_refs.head_sha, new_diff_refs.head_sha, straight: true)
      end

      def cd_diffs
        @cd_diffs ||= compare(new_diff_refs.start_sha, new_diff_refs.head_sha)
      end

      private

      def compare(start_sha, head_sha, straight: false)
        compare = CompareService.new(project, head_sha).execute(project, start_sha, straight: straight)
        compare.diffs(paths: paths, expanded: true)
      end
    end
  end
end