summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/parallel_diff.rb
blob: 74f9b3c050a616a62cb9a4c1e2bafb0b17734c90 (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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
module Gitlab
  module Diff
    class ParallelDiff
      attr_accessor :diff_file

      def initialize(diff_file)
        @diff_file = diff_file
      end

      def parallelize
        lines = []
        skip_next = false

        highlighted_diff_lines = diff_file.highlighted_diff_lines
        highlighted_diff_lines.each do |line|
          full_line = line.text
          type = line.type
          line_code = generate_line_code(diff_file.file_path, line)
          line_new = line.new_pos
          line_old = line.old_pos

          next_line = diff_file.next_line(line.index)

          if next_line
            next_line = highlighted_diff_lines[next_line.index]
            next_line_code = generate_line_code(diff_file.file_path, next_line)
            next_type = next_line.type
            next_line = next_line.text
          end

          case type
          when 'match', nil
            # line in the right panel is the same as in the left one
            lines << {
              left: {
                type:       type,
                number:     line_old,
                text:       full_line,
                line_code:  line_code,
              },
              right: {
                type:       type,
                number:     line_new,
                text:       full_line,
                line_code:  line_code
              }
            }
          when 'old'
            case next_type
            when 'new'
              # Left side has text removed, right side has text added
              lines << {
                left: {
                  type:       type,
                  number:     line_old,
                  text:       full_line,
                  line_code:  line_code,
                },
                right: {
                  type:       next_type,
                  number:     line_new,
                  text:       next_line,
                  line_code:  next_line_code
                }
              }
              skip_next = true
            when 'old', 'nonewline', nil
              # Left side has text removed, right side doesn't have any change
              # No next line code, no new line number, no new line text
              lines << {
                left: {
                  type:       type,
                  number:     line_old,
                  text:       full_line,
                  line_code:  line_code,
                },
                right: {
                  type:       next_type,
                  number:     nil,
                  text:       "",
                  line_code:  nil
                }
              }
            end
          when 'new'
            if skip_next
              # Change has been already included in previous line so no need to do it again
              skip_next = false
              next
            else
              # Change is only on the right side, left side has no change
              lines << {
                left: {
                  type:       nil,
                  number:     nil,
                  text:       "",
                  line_code:  line_code,
                },
                right: {
                  type:       type,
                  number:     line_new,
                  text:       full_line,
                  line_code:  line_code
                }
              }
            end
          end
        end
        lines
      end

      private

      def generate_line_code(file_path, line)
        Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
      end
    end
  end
end