Class: FileDiff

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

Constant Summary collapse

DIFF_REGEX =
/^@@ -\d+(,\d+)? \+\d+(,\d+)? @@/
FILE_INDEX_REGEX =
/index [0-9a-f]{7,40}/
BINARY_REGEX =
/^Binary files \/dev\/null and/
DELETION_REGEX =
/\[-.*?-\]/
INSERTION_REGEX =
/\{\+.*?\+\}/
DIFF_STAT_REGEX =
/^\d+\t\d+\t/
DELETE_REGEX =
/$\[-.*?-\]$/
DELETE_OP_REGEX =
/^deleted file/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ FileDiff

Returns a new instance of FileDiff.



24
25
26
27
28
# File 'lib/file_diff.rb', line 24

def initialize(attrs={})
  attrs.each do |key, val|
    instance_variable_set("@#{key}".to_sym, val)
  end
end

Instance Attribute Details

#a_file_idObject

Returns the value of attribute a_file_id.



17
18
19
# File 'lib/file_diff.rb', line 17

def a_file_id
  @a_file_id
end

#a_file_nameObject

Returns the value of attribute a_file_name.



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

def a_file_name
  @a_file_name
end

#b_file_idObject

Returns the value of attribute b_file_id.



18
19
20
# File 'lib/file_diff.rb', line 18

def b_file_id
  @b_file_id
end

#b_file_nameObject

Returns the value of attribute b_file_name.



16
17
18
# File 'lib/file_diff.rb', line 16

def b_file_name
  @b_file_name
end

#changes_totalObject

Returns the value of attribute changes_total.



22
23
24
# File 'lib/file_diff.rb', line 22

def changes_total
  @changes_total
end

#deletions_totalObject

Returns the value of attribute deletions_total.



21
22
23
# File 'lib/file_diff.rb', line 21

def deletions_total
  @deletions_total
end

#diffsObject

Returns the value of attribute diffs.



19
20
21
# File 'lib/file_diff.rb', line 19

def diffs
  @diffs
end

#insertions_totalObject

Returns the value of attribute insertions_total.



20
21
22
# File 'lib/file_diff.rb', line 20

def insertions_total
  @insertions_total
end

#operationObject

Returns the value of attribute operation.



14
15
16
# File 'lib/file_diff.rb', line 14

def operation
  @operation
end

Class Method Details

.from_git(file_diff_lines) ⇒ Object



31
32
33
# File 'lib/file_diff.rb', line 31

def from_git(file_diff_lines)
  FileDiff.new(parse_file_diff(file_diff_lines))
end

.parse_file_diff(file_diff_lines) ⇒ Object

TODO: Handle different file modes like new, move, and delete.



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
# File 'lib/file_diff.rb', line 36

def parse_file_diff(file_diff_lines)
  file_names = file_diff_lines
    .first
    .sub("diff --git a/", "")
    .split(" b/")

  a_file_name = file_names.first.strip()
  b_file_name = file_names.last.strip()

  file_index = file_diff_lines
    .each_index
    .detect { |i| file_diff_lines[i].match(FILE_INDEX_REGEX) }

  if file_index.nil?
    a_file_id = nil
    b_file_id = nil
  else
    a_file_id, b_file_id = file_diff_lines[file_index]
      .sub("index ", "")
      .split(" ")
      .first
      .split("..")
  end

  if file_diff_lines.last.match(BINARY_REGEX)
    operation = :binary
  elsif (a_file_name != b_file_name)
    operation = :move
  elsif (file_diff_lines[1].match(DELETE_OP_REGEX))
    operation = :delete
  else
    operation = :change
  end

  diff_index = file_diff_lines
    .each_index
    .detect { |i| file_diff_lines[i].match(DIFF_REGEX) }

  if diff_index.nil?
    diffs = []
  else
    diffs = file_diff_lines[diff_index..-1]
      .reduce([], &fold_reducer(DIFF_REGEX))
      .flat_map { |diff_lines| Diff.from_git(diff_lines) }
  end

  insertions = diffs.map { |diff| diff.insert_count }.reduce(0, :+)
  deletions = diffs.map { |diff| diff.delete_count }.reduce(0, :+)

  {
    operation: operation,
    a_file_name: a_file_name,
    b_file_name: b_file_name,
    a_file_id: a_file_id,
    b_file_id: b_file_id,
    diffs: diffs,
    insertions_total: insertions,
    deletions_total: deletions,
    changes_total: insertions + deletions
  }
end