BigW Consortium Gitlab

parser.rb 2.31 KB
Newer Older
1 2 3 4 5
module Gitlab
  module Diff
    class Parser
      include Enumerable

6
      def parse(lines)
7 8
        return [] if lines.blank?

9
        @lines = lines
10 11 12 13
        line_obj_index = 0
        line_old = 1
        line_new = 1
        type = nil
14
        context = nil
15

16 17 18 19 20
        # By returning an Enumerator we make it possible to search for a single line (with #find)
        # without having to instantiate all the others that come after it.
        Enumerator.new do |yielder|
          @lines.each do |line|
            next if filename?(line)
21

22
            full_line = line.delete("\n")
23

24
            if line =~ /^@@ -/
25
              type = "match"
26

27 28
              line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
              line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
29 30

              next if line_old <= 1 && line_new <= 1 # top of file
31 32 33 34
              yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
              line_obj_index += 1
              next
            elsif line[0] == '\\'
35 36
              type = "#{context}-nonewline"

37 38 39 40 41 42 43
              yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
              line_obj_index += 1
            else
              type = identification_type(line)
              yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
              line_obj_index += 1
            end
44

45 46 47
            case line[0]
            when "+"
              line_new += 1
48
              context = :new
49 50
            when "-"
              line_old += 1
51
              context = :old
52
            when "\\" # rubocop:disable Lint/EmptyWhen
53 54 55 56 57
              # No increment
            else
              line_new += 1
              line_old += 1
            end
58 59 60 61 62 63 64 65 66 67 68
          end
        end
      end

      def empty?
        @lines.empty?
      end

      private

      def filename?(line)
69 70 71
        line.start_with?( '--- /dev/null', '+++ /dev/null', '--- a', '+++ b',
                          '+++ a', # The line will start with `+++ a` in the reverse diff of an orphan commit
                          '--- /tmp/diffy', '+++ /tmp/diffy')
72 73 74
      end

      def identification_type(line)
75 76
        case line[0]
        when "+"
77
          "new"
78
        when "-"
79 80 81 82 83 84 85 86
          "old"
        else
          nil
        end
      end
    end
  end
end