Class: Leg::Diff

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename = nil, is_new_file = false, lines = []) ⇒ Diff

Returns a new instance of Diff.



5
6
7
8
9
# File 'lib/leg/diff.rb', line 5

def initialize(filename = nil, is_new_file = false, lines = [])
  @filename = filename
  @is_new_file = is_new_file
  @lines = lines
end

Instance Attribute Details

#filenameObject

Returns the value of attribute filename.



3
4
5
# File 'lib/leg/diff.rb', line 3

def filename
  @filename
end

#is_new_fileObject

Returns the value of attribute is_new_file.



3
4
5
# File 'lib/leg/diff.rb', line 3

def is_new_file
  @is_new_file
end

#linesObject

Returns the value of attribute lines.



3
4
5
# File 'lib/leg/diff.rb', line 3

def lines
  @lines
end

Class Method Details

.parse(git_diff) ⇒ Object

Parse a git diff and return an array of Diff objects, one for each file in the git diff.



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
# File 'lib/leg/diff.rb', line 51

def self.parse(git_diff)
  in_diff = false
  old_line_num = nil
  new_line_num = nil
  cur_diff = nil
  diffs = []

  git_diff.lines.each do |line|
    if line =~ /^--- (.+)$/
      cur_diff = Leg::Diff.new
      if $1 == '/dev/null'
        cur_diff.is_new_file = true
      end
      diffs << cur_diff
      in_diff = false
    elsif line =~ /^\+\+\+ (.+)$/
      cur_diff.filename = $1.strip.sub(/^b\//, '')
    elsif line =~ /^@@ -(\d+)(,\d+)? \+(\d+)(,\d+)? @@/
      # TODO: somehow preserve function name that comes to the right of the @@ header?
      in_diff = true
      old_line_num = $1.to_i
      new_line_num = $3.to_i
    elsif in_diff && line[0] == '\\'
      # Ignore "\ No newline at end of file".
    elsif in_diff && [' ', '|', '+', '-'].include?(line[0])
      case line[0]
      when ' ', '|'
        line_nums = [old_line_num, new_line_num]
        old_line_num += 1
        new_line_num += 1
        cur_diff << Leg::Line::Unchanged.new(line[1..-1], line_nums)
      when '+'
        line_nums = [nil, new_line_num]
        new_line_num += 1
        cur_diff << Leg::Line::Added.new(line[1..-1], line_nums)
      when '-'
        line_nums = [old_line_num, nil]
        old_line_num += 1
        cur_diff << Leg::Line::Removed.new(line[1..-1], line_nums)
      end
    else
      in_diff = false
    end
  end

  diffs
end

Instance Method Details

#<<(line) ⇒ Object

Append a Line to the Diff.



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

def <<(line)
  unless line.is_a? Leg::Line
    raise ArgumentError, "expected a Line"
  end
  @lines << line
  self
end

#cloneObject



11
12
13
# File 'lib/leg/diff.rb', line 11

def clone
  Leg::Diff.new(@filename.dup, @is_new_file, @lines.map(&:clone))
end

#clone_emptyObject



15
16
17
# File 'lib/leg/diff.rb', line 15

def clone_empty
  Leg::Diff.new(@filename.dup, @is_new_file, [])
end

#to_patch(options = {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/leg/diff.rb', line 28

def to_patch(options = {})
  patch = ""
  patch += "diff --git a/#{@filename} b/#{@filename}\n" unless options[:strip_git_lines]
  if @is_new_file
    patch += "new file mode 100644\n" unless options[:strip_git_lines]
    patch += "--- /dev/null\n"
  else
    patch += "--- #{'a/' unless options[:strip_git_lines]}#{@filename}\n"
  end
  patch += "+++ #{'b/' unless options[:strip_git_lines]}#{@filename}\n"

  find_hunks.each do |hunk|
    patch += hunk_header(hunk)
    hunk.each do |line|
      patch += line.to_patch(options)
    end
  end

  patch
end