diff_json 0.1.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/diff_json.rb +3 -3
- data/lib/diff_json/diff.rb +77 -479
- data/lib/diff_json/diff/json_diffing.rb +201 -0
- data/lib/diff_json/diff/json_mapping.rb +122 -0
- data/lib/diff_json/output/html_output.rb +268 -0
- data/lib/diff_json/{undefined_value.rb → output/undefined_value.rb} +0 -0
- metadata +27 -12
- data/lib/diff_json/html_output.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08af726b4ce91a316f8143a343d18ee82207d95afda7ccd08ad22f9f416cb913'
|
4
|
+
data.tar.gz: 39a56823c4a9ea78ba38f418a3242fc998ae394adaca7e72f09c7b86f07fe306
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93fb867871e15cd864b7558dfe7b6211ce5f1e59c4659c3d4f2f5efb0f2a37d8c041b2a041785d36ec375a7dddf2233030f014ccf1c31b7164985707ad81efbf
|
7
|
+
data.tar.gz: 56e4b5053dca4018508a458fb359075c2e8e3ad738b8ef929843a9430c2f84a7eca6d3377f71493e880f2156b303ab758985e71356d60f454d655bf1179d6f66
|
data/lib/diff_json.rb
CHANGED
data/lib/diff_json/diff.rb
CHANGED
@@ -1,505 +1,103 @@
|
|
1
|
-
|
2
|
-
class Diff
|
3
|
-
def initialize(old_json, new_json, **opts)
|
4
|
-
@old_json = old_json
|
5
|
-
@new_json = new_json
|
6
|
-
@opts = {
|
7
|
-
:debug => false,
|
8
|
-
:diff_count_filter => {
|
9
|
-
:only => ['$**'],
|
10
|
-
:except => []
|
11
|
-
},
|
12
|
-
:ignore_object_keys => [],
|
13
|
-
:generate_object_sub_diffs => {}
|
14
|
-
}.merge(opts)
|
15
|
-
@filtered = @opts[:diff_count_filter] != {
|
16
|
-
:only => ['$**'],
|
17
|
-
:except => []
|
18
|
-
}
|
19
|
-
@diff = {
|
20
|
-
:count => {
|
21
|
-
:all => 0,
|
22
|
-
:insert => 0,
|
23
|
-
:update => 0,
|
24
|
-
:delete => 0,
|
25
|
-
:move => 0
|
26
|
-
},
|
27
|
-
:full_diff => {
|
28
|
-
:old => [],
|
29
|
-
:new => []
|
30
|
-
},
|
31
|
-
:sub_diffs => {}
|
32
|
-
}
|
33
|
-
|
34
|
-
calculate
|
35
|
-
end
|
36
|
-
|
37
|
-
def diff
|
38
|
-
return @diff[:full_diff]
|
39
|
-
end
|
40
|
-
|
41
|
-
def sub_diffs
|
42
|
-
return @diff[:sub_diffs]
|
43
|
-
end
|
44
|
-
|
45
|
-
def change_count(operation = :all)
|
46
|
-
return @diff[:count][operation] || 0
|
47
|
-
end
|
48
|
-
|
49
|
-
def retrieve_output(output_type = :stdout, **output_opts)
|
50
|
-
case output_type
|
51
|
-
when :stdout
|
52
|
-
when :file
|
53
|
-
when :html
|
54
|
-
html_output = HtmlOutput.new(self, **output_opts)
|
55
|
-
return html_output
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def calculate
|
62
|
-
@diff[:full_diff][:old], @diff[:full_diff][:new] = compare_elements(@old_json, @new_json)
|
63
|
-
|
64
|
-
@diff[:sub_diffs].each do |key, sub_diffs|
|
65
|
-
sub_diffs.each do |value, diff|
|
66
|
-
diff[:old] = [] unless diff.key?(:old)
|
67
|
-
diff[:new] = [] unless diff.key?(:new)
|
68
|
-
|
69
|
-
diff[:old], diff[:new] = add_blank_lines(diff[:old], diff[:new])
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def compare_elements(old_element, new_element, indent_step = 0, path = '$')
|
75
|
-
debug([
|
76
|
-
'ENTER compare_elements',
|
77
|
-
"Diffing #{path}"
|
78
|
-
])
|
79
|
-
|
80
|
-
old_element_lines, new_element_lines = [], []
|
1
|
+
require_rel './diff'
|
81
2
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
old_element_lines = JSON.pretty_generate(old_element, max_nesting: false, quirks_mode: true).split("\n").map{|el| [' ', "#{indentation(indent_step)}#{el}"]}
|
86
|
-
new_element_lines = JSON.pretty_generate(new_element, max_nesting: false, quirks_mode: true).split("\n").map{|el| [' ', "#{indentation(indent_step)}#{el}"]}
|
87
|
-
else
|
88
|
-
unless value_type(old_element) == value_type(new_element)
|
89
|
-
debug('Opposite type element, no diff required')
|
90
|
-
|
91
|
-
increment_diff_count(path, :insert)
|
92
|
-
increment_diff_count(path, :delete)
|
93
|
-
old_element_lines, new_element_lines = add_blank_lines(
|
94
|
-
JSON.pretty_generate(old_element, max_nesting: false, quirks_mode: true).split("\n").map{|el| ['-', "#{indentation(indent_step)}#{el}"]},
|
95
|
-
JSON.pretty_generate(new_element, max_nesting: false, quirks_mode: true).split("\n").map{|el| ['+', "#{indentation(indent_step)}#{el}"]}
|
96
|
-
)
|
97
|
-
else
|
98
|
-
debug("Found #{value_type(old_element)}, diffing")
|
99
|
-
|
100
|
-
increment_diff_count(path, :update)
|
101
|
-
old_element_lines, new_element_lines = self.send("#{value_type(old_element)}_diff", old_element, new_element, indent_step, path)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
return old_element_lines, new_element_lines
|
106
|
-
end
|
107
|
-
|
108
|
-
def array_diff(old_array, new_array, indent_step, base_path)
|
109
|
-
debug('ENTER array_diff')
|
110
|
-
|
111
|
-
oal, nal = old_array.length, new_array.length
|
112
|
-
sal = oal < nal ? oal : nal
|
113
|
-
lal = oal > nal ? oal : nal
|
114
|
-
old_array_lines, new_array_lines = [[' ', "#{indentation(indent_step)}["]], [[' ', "#{indentation(indent_step)}["]]
|
115
|
-
next_step = indent_step + 1
|
116
|
-
operations = {
|
117
|
-
'none' => [],
|
118
|
-
'arr_add_index' => [],
|
119
|
-
'arr_drop_index' => [],
|
120
|
-
'arr_send_move' => [],
|
121
|
-
'arr_receive_move' => []
|
122
|
-
}
|
123
|
-
|
124
|
-
# Find indices that were added or dropped, if any
|
125
|
-
if oal < nal
|
126
|
-
operations['arr_add_index'] += (oal..(nal - 1)).to_a
|
127
|
-
elsif oal > nal
|
128
|
-
operations['arr_drop_index'] += (nal..(oal - 1)).to_a
|
129
|
-
end
|
130
|
-
|
131
|
-
# Find 'none' and 'move_value' operations
|
132
|
-
(old_array | new_array).each do |v|
|
133
|
-
# For a given value, find all indices of each array that corresponds
|
134
|
-
old_indices, new_indices = array_indices(old_array, v), array_indices(new_array, v)
|
135
|
-
# Same index, same value, no diff necessary
|
136
|
-
operations['none'] += (old_indices & new_indices)
|
137
|
-
|
138
|
-
# Pull the skipped indices before calculating movements
|
139
|
-
old_indices -= operations['none']
|
140
|
-
new_indices -= operations['none']
|
141
|
-
|
142
|
-
# Find values that were moved from one index to another
|
143
|
-
if !old_indices.empty? and !new_indices.empty?
|
144
|
-
max_moves = old_indices.length < new_indices.length ? old_indices.length : new_indices.length
|
145
|
-
possible_moves = []
|
146
|
-
# Make pairs of possible moves
|
147
|
-
old_indices.each do |oi|
|
148
|
-
new_indices.each do |ni|
|
149
|
-
possible_moves << [(oi - ni).abs, [oi, ni]]
|
150
|
-
end
|
151
|
-
end
|
152
|
-
# For the sake of simplicity, we'll arbitrarily decide to use the shortest moves
|
153
|
-
possible_moves.sort!{|x,y| x[0] <=> y[0]}
|
154
|
-
# Take the first (max_moves) moves and add their operations
|
155
|
-
possible_moves[0..(max_moves - 1)].each do |move|
|
156
|
-
operations['arr_send_move'] << move[1][0]
|
157
|
-
operations['arr_receive_move'] << move[1][1]
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# Add base diff for each index
|
163
|
-
(0..(lal - 1)).each do |i|
|
164
|
-
debug("PROCESS INDEX #{i}")
|
165
|
-
|
166
|
-
item_path = "#{base_path}[#{i}]"
|
167
|
-
old_item_lines, new_item_lines = [], []
|
168
|
-
item_diff_operations = []
|
169
|
-
last_loop = (i == (lal - 1))
|
170
|
-
|
171
|
-
# Assign current known operations to each index
|
172
|
-
(operations.keys).each do |operation|
|
173
|
-
if operations[operation].include?(i)
|
174
|
-
item_diff_operations << operation
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# Add arr_change_value, arr_add_value, and arr_drop_value operations
|
179
|
-
if item_diff_operations.empty?
|
180
|
-
item_diff_operations << 'arr_change_value'
|
181
|
-
elsif (
|
182
|
-
item_diff_operations.include?('arr_send_move') and
|
183
|
-
!item_diff_operations.include?('arr_receive_move') and
|
184
|
-
!item_diff_operations.include?('arr_drop_index')
|
185
|
-
)
|
186
|
-
item_diff_operations << 'arr_add_value'
|
187
|
-
elsif (
|
188
|
-
!item_diff_operations.include?('arr_send_move') and
|
189
|
-
item_diff_operations.include?('arr_receive_move') and
|
190
|
-
!item_diff_operations.include?('arr_add_index')
|
191
|
-
)
|
192
|
-
item_diff_operations << 'arr_drop_value'
|
193
|
-
end
|
194
|
-
|
195
|
-
# Call compare_elements for sub-elements if necessary
|
196
|
-
if (!(item_diff_operations & ['none', 'arr_change_value']).empty? and
|
197
|
-
is_json_element?(old_array[i]) and is_json_element?(new_array[i])
|
198
|
-
)
|
199
|
-
old_item_lines, new_item_lines = compare_elements(old_array[i], new_array[i], next_step, item_path)
|
200
|
-
else
|
201
|
-
# Grab old and new items
|
202
|
-
# UndefinedValue class is here to represent the difference between explicit null and non-existent
|
203
|
-
old_item = item_diff_operations.include?('arr_add_index') ? UndefinedValue.new : old_array[i]
|
204
|
-
new_item = item_diff_operations.include?('arr_drop_index') ? UndefinedValue.new : new_array[i]
|
205
|
-
|
206
|
-
# Figure out operators for left and right
|
207
|
-
if item_diff_operations.include?('none')
|
208
|
-
old_operator, new_operator = ' ', ' '
|
209
|
-
elsif item_diff_operations.include?('arr_change_value')
|
210
|
-
increment_diff_count(item_path, :update)
|
211
|
-
old_operator, new_operator = '-', '+'
|
212
|
-
elsif (item_diff_operations & ['arr_send_move', 'arr_receive_move']).length == 2
|
213
|
-
increment_diff_count(item_path, :move)
|
214
|
-
old_operator, new_operator = 'M', 'M'
|
215
|
-
elsif item_diff_operations.include?('arr_add_value')
|
216
|
-
increment_diff_count(item_path, :insert)
|
217
|
-
old_operator, new_operator = 'M', '+'
|
218
|
-
elsif item_diff_operations.include?('arr_drop_value')
|
219
|
-
increment_diff_count(item_path, :delete)
|
220
|
-
old_operator, new_operator = '-', 'M'
|
221
|
-
elsif item_diff_operations.include?('arr_drop_index')
|
222
|
-
if item_diff_operations.include?('arr_send_move')
|
223
|
-
increment_diff_count(item_path, :move)
|
224
|
-
old_operator, new_operator = 'M', ' '
|
225
|
-
else
|
226
|
-
increment_diff_count(item_path, :delete)
|
227
|
-
old_operator, new_operator = '-', ' '
|
228
|
-
end
|
229
|
-
elsif item_diff_operations.include?('arr_add_index')
|
230
|
-
if item_diff_operations.include?('arr_receive_move')
|
231
|
-
old_operator, new_operator = ' ', 'M'
|
232
|
-
else
|
233
|
-
increment_diff_count(item_path, :insert)
|
234
|
-
old_operator, new_operator = ' ', '+'
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
# Gather lines
|
239
|
-
if old_item.is_a?(UndefinedValue)
|
240
|
-
new_item_lines = JSON.pretty_generate(new_item, max_nesting: false, quirks_mode: true).split("\n").map{|il| [new_operator, "#{indentation(next_step)}#{il}"]}
|
241
|
-
|
242
|
-
(0..(new_item_lines.length - 1)).each do |i|
|
243
|
-
old_item_lines << [' ', '']
|
244
|
-
end
|
245
|
-
else
|
246
|
-
old_item_lines = JSON.pretty_generate(old_item, max_nesting: false, quirks_mode: true).split("\n").map{|il| [old_operator, "#{indentation(next_step)}#{il}"]}
|
247
|
-
end
|
248
|
-
|
249
|
-
if new_item.is_a?(UndefinedValue)
|
250
|
-
(0..(old_item_lines.length - 1)).each do |i|
|
251
|
-
new_item_lines << [' ', '']
|
252
|
-
end
|
253
|
-
else
|
254
|
-
new_item_lines = JSON.pretty_generate(new_item, max_nesting: false, quirks_mode: true).split("\n").map{|il| [new_operator, "#{indentation(next_step)}#{il}"]}
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
unless old_item_lines.empty?
|
259
|
-
old_item_lines.last[1] = "#{old_item_lines.last[1]}," if !last_loop and (old_item_lines.last[1].match(/[^\s]/))
|
260
|
-
end
|
261
|
-
unless new_item_lines.empty?
|
262
|
-
new_item_lines.last[1] = "#{new_item_lines.last[1]}," if !last_loop and (new_item_lines.last[1].match(/[^\s]/))
|
263
|
-
end
|
264
|
-
|
265
|
-
add_object_sub_diff_if_required(item_path, old_item, old_item_lines) if old_item.is_a?(Hash) and old_operator == '-'
|
266
|
-
add_object_sub_diff_if_required(item_path, new_item, new_item_lines, :new) if new_item.is_a?(Hash) and new_operator == '+'
|
267
|
-
|
268
|
-
old_item_lines, new_item_lines = add_blank_lines(old_item_lines, new_item_lines)
|
269
|
-
|
270
|
-
old_array_lines += old_item_lines
|
271
|
-
new_array_lines += new_item_lines
|
272
|
-
end
|
273
|
-
|
274
|
-
old_array_lines << [' ', "#{indentation(indent_step)}]"]
|
275
|
-
new_array_lines << [' ', "#{indentation(indent_step)}]"]
|
276
|
-
|
277
|
-
return old_array_lines, new_array_lines
|
278
|
-
end
|
279
|
-
|
280
|
-
def object_diff(old_object, new_object, indent_step, base_path)
|
281
|
-
debug('ENTER object_diff')
|
282
|
-
|
283
|
-
keys = {
|
284
|
-
'all' => (old_object.keys | new_object.keys),
|
285
|
-
'common' => (old_object.keys & new_object.keys),
|
286
|
-
'add' => (new_object.keys - old_object.keys),
|
287
|
-
'drop' => (old_object.keys - new_object.keys)
|
288
|
-
}
|
289
|
-
old_object_lines, new_object_lines = [[' ', "#{indentation(indent_step)}{"]], [[' ', "#{indentation(indent_step)}{"]]
|
290
|
-
next_step = indent_step + 1
|
291
|
-
|
292
|
-
# For objects, we're taking a much simpler approach, so no movements
|
293
|
-
keys['all'].each do |k|
|
294
|
-
debug("PROCESS KEY #{k}")
|
295
|
-
|
296
|
-
item_path = "#{base_path}{#{k}}"
|
297
|
-
key_string = "#{JSON.pretty_generate(k, max_nesting: false, quirks_mode: true)}: "
|
298
|
-
old_item_lines, new_item_lines = [], []
|
299
|
-
last_loop = (k == keys['all'].last)
|
300
|
-
|
301
|
-
if keys['common'].include?(k)
|
302
|
-
if is_json_element?(old_object[k]) and is_json_element?(new_object[k]) and !@opts[:ignore_object_keys].include?(k)
|
303
|
-
old_item_lines, new_item_lines = compare_elements(old_object[k], new_object[k], next_step, item_path)
|
304
|
-
else
|
305
|
-
if old_object[k] == new_object[k] or @opts[:ignore_object_keys].include?(k)
|
306
|
-
old_item_lines = JSON.pretty_generate(old_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| [' ', "#{indentation(next_step)}#{il}"]}
|
307
|
-
new_item_lines = JSON.pretty_generate(new_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| [' ', "#{indentation(next_step)}#{il}"]}
|
308
|
-
else
|
309
|
-
increment_diff_count(item_path, :update)
|
310
|
-
old_item_lines = JSON.pretty_generate(old_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| ['-', "#{indentation(next_step)}#{il}"]}
|
311
|
-
new_item_lines = JSON.pretty_generate(new_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| ['+', "#{indentation(next_step)}#{il}"]}
|
312
|
-
end
|
313
|
-
end
|
314
|
-
else
|
315
|
-
if keys['drop'].include?(k)
|
316
|
-
increment_diff_count(item_path, :delete) unless @opts[:ignore_object_keys].include?(k)
|
317
|
-
old_item_lines = JSON.pretty_generate(old_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| [@opts[:ignore_object_keys].include?(k) ? ' ' : '-', "#{indentation(next_step)}#{il}"]}
|
318
|
-
new_item_lines = []
|
319
|
-
|
320
|
-
(0..(old_item_lines.length - 1)).each do |i|
|
321
|
-
new_item_lines << [' ', '']
|
322
|
-
end
|
323
|
-
elsif keys['add'].include?(k)
|
324
|
-
increment_diff_count(item_path, :insert) unless @opts[:ignore_object_keys].include?(k)
|
325
|
-
new_item_lines = JSON.pretty_generate(new_object[k], max_nesting: false, quirks_mode: true).split("\n").map!{|il| [@opts[:ignore_object_keys].include?(k) ? ' ' : '+', "#{indentation(next_step)}#{il}"]}
|
326
|
-
old_item_lines = []
|
3
|
+
module DiffJson
|
4
|
+
def self.diff(old_json, new_json, return_type, diff_opts = {}, output_opts = {})
|
5
|
+
completed_diff = Diff.new(old_json, new_json, **diff_opts)
|
327
6
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
7
|
+
return case return_type
|
8
|
+
when :raw
|
9
|
+
completed_diff
|
10
|
+
when :patch
|
11
|
+
patch_operations = []
|
333
12
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
end
|
338
|
-
unless new_item_lines.empty?
|
339
|
-
new_item_lines[0][1].gsub!(/^(?<spaces>\s+)(?<content>.+)$/, "\\k<spaces>#{key_string}\\k<content>")
|
340
|
-
new_item_lines.last[1] = "#{new_item_lines.last[1]}," if !last_loop and (new_item_lines.last[1].match(/[^\s]/))
|
13
|
+
completed_diff.diff.each do |path, operations|
|
14
|
+
operations.each do |op|
|
15
|
+
patch_operations << op if [:add, :replace, :remove].include?(op[:op]) or (op[:op] == :move and path == op[:from])
|
341
16
|
end
|
342
|
-
|
343
|
-
old_item_lines, new_item_lines = add_blank_lines(old_item_lines, new_item_lines)
|
344
|
-
|
345
|
-
old_object_lines += old_item_lines
|
346
|
-
new_object_lines += new_item_lines
|
347
17
|
end
|
348
18
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
add_object_sub_diff_if_required(base_path, old_object, old_object_lines)
|
353
|
-
add_object_sub_diff_if_required(base_path, new_object, new_object_lines, :new)
|
354
|
-
|
355
|
-
return old_object_lines, new_object_lines
|
356
|
-
end
|
357
|
-
|
358
|
-
def debug(message)
|
359
|
-
puts message if @opts[:debug]
|
360
|
-
end
|
361
|
-
|
362
|
-
def array_indices(array, value)
|
363
|
-
indices = []
|
364
|
-
|
365
|
-
array.each_with_index do |av,i|
|
366
|
-
indices << i if av == value
|
367
|
-
end
|
368
|
-
|
369
|
-
return indices
|
19
|
+
return patch_operations
|
20
|
+
when :html
|
21
|
+
HtmlOutput.new(completed_diff, **output_opts)
|
370
22
|
end
|
23
|
+
end
|
371
24
|
|
372
|
-
|
373
|
-
|
374
|
-
|
25
|
+
class Diff
|
26
|
+
include JsonMapping
|
27
|
+
include JsonDiffing
|
375
28
|
|
376
|
-
def
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
29
|
+
def initialize(old_json, new_json, **opts)
|
30
|
+
# Set config options
|
31
|
+
@opts = {
|
32
|
+
count_operations: {
|
33
|
+
'/**' => [:add, :replace, :remove, :move, :update]
|
34
|
+
},
|
35
|
+
ignore_paths: [],
|
36
|
+
path_sort: :sorted,
|
37
|
+
sub_diffs: {},
|
38
|
+
track_array_moves: true,
|
39
|
+
track_structure_updates: false,
|
40
|
+
replace_primitives_arrays: false,
|
41
|
+
logger: ::Logger.new(STDOUT),
|
42
|
+
log_level: :warn
|
43
|
+
}.merge(opts)
|
44
|
+
# Create map of both JSON objects
|
45
|
+
@old_map = map_json(old_json, '', 0)
|
46
|
+
@new_map = map_json(new_json, '', 0)
|
47
|
+
# Gather the full list of all paths in both JSON objects in a consistent order
|
48
|
+
@all_paths = gather_paths(@old_map.keys, @new_map.keys, @opts[:path_sort] == :sorted)
|
49
|
+
# Generate diff operations list
|
50
|
+
@diff = diff_check(old_json, new_json)
|
51
|
+
# Find difference counts
|
52
|
+
@counts = find_counts(@diff)
|
53
|
+
# Gather sub-diffs
|
54
|
+
@sub_diffs = generate_sub_diffs
|
55
|
+
end
|
56
|
+
|
57
|
+
def count(count_type = :all)
|
58
|
+
return case count_type
|
59
|
+
when :ignore, :add, :replace, :remove, :move, :update
|
60
|
+
@counts[count_type] || 0
|
61
|
+
when :total
|
62
|
+
@counts.values.sum
|
384
63
|
else
|
385
|
-
|
64
|
+
@counts
|
386
65
|
end
|
387
66
|
end
|
388
67
|
|
389
|
-
def
|
390
|
-
|
391
|
-
' ' * step
|
68
|
+
def diff
|
69
|
+
return @diff
|
392
70
|
end
|
393
71
|
|
394
|
-
def
|
395
|
-
|
396
|
-
(1..(right_lines.length - left_lines.length)).each do
|
397
|
-
left_lines << [' ', '']
|
398
|
-
end
|
399
|
-
elsif left_lines.length > right_lines.length
|
400
|
-
(1..(left_lines.length - right_lines.length)).each do
|
401
|
-
right_lines << [' ', '']
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
return left_lines, right_lines
|
72
|
+
def json_map(version = :old)
|
73
|
+
return (version == :old ? @old_map : @new_map)
|
406
74
|
end
|
407
75
|
|
408
|
-
def
|
409
|
-
|
410
|
-
|
76
|
+
def paths(version = :joint)
|
77
|
+
return case version
|
78
|
+
when :old
|
79
|
+
json_map(:old).keys
|
80
|
+
when :new
|
81
|
+
json_map(:new).keys
|
411
82
|
else
|
412
|
-
|
413
|
-
|
414
|
-
# Any path prefixes in `only` that match?
|
415
|
-
if (
|
416
|
-
@opts[:diff_count_filter].key?(:only) and
|
417
|
-
@opts[:diff_count_filter][:only].is_a?(Array) and
|
418
|
-
!@opts[:diff_count_filter][:only].empty?
|
419
|
-
)
|
420
|
-
@opts[:diff_count_filter][:only].each do |only_path|
|
421
|
-
unless ['none', 'lower'].include?(path_inclusion(path, only_path))
|
422
|
-
do_count = true
|
423
|
-
break
|
424
|
-
else
|
425
|
-
next
|
426
|
-
end
|
427
|
-
end
|
428
|
-
else
|
429
|
-
# If :only is empty or non-existent, count everything
|
430
|
-
do_count = true
|
431
|
-
end
|
432
|
-
|
433
|
-
# Make sure the specific path is not excluded, if we've established that we should probably include it
|
434
|
-
if (
|
435
|
-
do_count and
|
436
|
-
@opts[:diff_count_filter].key?(:except) and
|
437
|
-
@opts[:diff_count_filter][:except].is_a?(Array) and
|
438
|
-
!@opts[:diff_count_filter][:except].empty?
|
439
|
-
)
|
440
|
-
@opts[:diff_count_filter][:except].each do |except_path|
|
441
|
-
unless ['none', 'lower'].include?(path_inclusion(path, except_path))
|
442
|
-
do_count = false
|
443
|
-
break
|
444
|
-
else
|
445
|
-
next
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
# Ensure this operation is allowed for counting
|
451
|
-
if (
|
452
|
-
do_count and
|
453
|
-
@opts[:diff_count_filter].key?(:operations) and
|
454
|
-
@opts[:diff_count_filter][:operations].is_a?(Array)
|
455
|
-
)
|
456
|
-
do_count = false if (
|
457
|
-
!@opts[:diff_count_filter][:operations].empty? and
|
458
|
-
!@opts[:diff_count_filter][:operations].include?(operation)
|
459
|
-
)
|
460
|
-
end
|
461
|
-
|
462
|
-
debug("Post-operation, #{do_count}")
|
463
|
-
|
464
|
-
@diff[:count][:all] += 1 if do_count
|
465
|
-
@diff[:count][operation] += 1 if do_count
|
83
|
+
@all_paths
|
466
84
|
end
|
467
85
|
end
|
468
86
|
|
469
|
-
def
|
470
|
-
|
471
|
-
check_path_wildcard = check_path.gsub(/[^\*]/, '') || ''
|
472
|
-
check = 'lower'
|
473
|
-
|
474
|
-
if current_path == check_path_base
|
475
|
-
check = 'exact' if check_path_wildcard == ''
|
476
|
-
check = 'lower'
|
477
|
-
elsif current_path.include?(check_path_base)
|
478
|
-
current_path_remainder = current_path.gsub(check_path_base, '')
|
479
|
-
current_path_remainder_steps = current_path_remainder.split(/(\]\[|\]\{|\}\[|\}\{)/)
|
480
|
-
|
481
|
-
check = 'level' if (current_path_remainder_steps.length == 1 and check_path_wildcard == '*')
|
482
|
-
check = 'recurse' if (current_path_remainder_steps.length > 0 and check_path_wildcard == '**')
|
483
|
-
else
|
484
|
-
check = 'none'
|
485
|
-
end
|
486
|
-
|
487
|
-
return check
|
87
|
+
def sub_diffs
|
88
|
+
return @sub_diffs
|
488
89
|
end
|
489
90
|
|
490
|
-
def
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
@diff[:sub_diffs][v][object[v]][side] = lines if object.key?(v)
|
501
|
-
end
|
502
|
-
end
|
91
|
+
def log_message(log_level, message)
|
92
|
+
log_levels = [
|
93
|
+
:debug,
|
94
|
+
:info,
|
95
|
+
:warn,
|
96
|
+
:error
|
97
|
+
]
|
98
|
+
|
99
|
+
if (log_levels.index(log_level) || -1) >= (log_levels.index(@opts[:log_level]) || 0)
|
100
|
+
@opts[:logger].method(log_level).call((is_structure?(message) ? JSON.pretty_generate(message) : message))
|
503
101
|
end
|
504
102
|
end
|
505
103
|
end
|