Class: Shiba::Review::Diff::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/shiba/review/diff.rb

Constant Summary collapse

FILE_PATTERN =

+++ b/config/environments/test.rb

/\A\+\+\+ b\/(.*?)\Z/
LINE_PATTERN =

@@ -177,0 178 @@ … @@ -177,0 178,5 @@ … @@ -21 +24 @@ …

/\A@@ \-\d+,?\d+? \+(\d+),?(\d+)? @@/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ Parser

Returns a new instance of Parser.



20
21
22
23
24
25
26
27
# File 'lib/shiba/review/diff.rb', line 20

def initialize(file)
  # Fixme. seems like enumerables should work in general.
  if !file.respond_to?(:pos)
    raise StandardError.new("Diff file does not appear to be a seekable IO object.")
  end
  @diff = file
  @status = :new
end

Instance Attribute Details

#statusObject (readonly)

via developer.github.com/v3/pulls/comments/#create-a-comment The position value equals the number of lines down from the first “@@” hunk header in the file you want to add a comment.



18
19
20
# File 'lib/shiba/review/diff.rb', line 18

def status
  @status
end

Instance Method Details

#find_position(path, line_number) ⇒ Object

Returns the position in the diff, after the relevant file header, that contains the specified file/lineno modification. Only supports finding the position in the destination / newest version of the file.

Example: diff = Diff.new(‘git diff`) diff.find_position(“test.rb”, 3)

> 5



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
# File 'lib/shiba/review/diff.rb', line 69

def find_position(path, line_number)
  io = @diff.each_line # maybe redundant?

  file_header = "+++ b/#{path}\n" # fixme
  if !io.find_index(file_header)
    @status = :file_not_found
    return
  end

  line = io.peek
  if !hunk_header?(line)
    raise StandardError.new("Expected hunk header to be after file header, but got '#{line}'")
  end

  pos = 0

  while true
    line = io.next
    pos += 1

    if file_header?(line)
      @status = :line_not_found
      return
    end

    if !hunk_header?(line)
      next
    end

    line_numbers = line_numbers_for_destination(line)

    if destination_position = line_numbers.find_index(line_number)
      @status = :found_position
      return pos + find_hunk_index(io, destination_position)
    end
  end
rescue StopIteration
  @status = :line_not_found
end

#updated_linesObject

Returns the file and line numbers that contain inserts. Deletions are ignored. For simplicity, the default output of git diff is not supported. The expected format is from ‘git diff unified=0’

Example: diff = ‘git diff –unified=0` Diff.new(StringIO.new(diff))

> [ [ “hello.rb”, 1..3 ]

> [ “hello.rb”, 7..7 ]

> [ “test.rb”, 23..23 ]

> ]



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/shiba/review/diff.rb', line 40

def updated_lines
  io = @diff.each_line
  path = nil

  found = []

  while true
    line = io.next
    if line =~ FILE_PATTERN
      path = $1
    end

    if hunk_header?(line)
      line_numbers = line_numbers_for_destination(line)
      found << [ path, line_numbers ]
    end
  end
rescue StopIteration
  return found
end