diff-lcs 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Contributing.md +2 -0
- data/History.md +86 -55
- data/License.md +6 -4
- data/Rakefile +36 -27
- data/bin/htmldiff +4 -4
- data/lib/diff/lcs/array.rb +1 -1
- data/lib/diff/lcs/backports.rb +2 -2
- data/lib/diff/lcs/block.rb +4 -4
- data/lib/diff/lcs/callbacks.rb +9 -7
- data/lib/diff/lcs/change.rb +19 -19
- data/lib/diff/lcs/htmldiff.rb +24 -16
- data/lib/diff/lcs/hunk.rb +35 -30
- data/lib/diff/lcs/internals.rb +17 -17
- data/lib/diff/lcs/ldiff.rb +37 -35
- data/lib/diff/lcs.rb +57 -55
- data/lib/diff-lcs.rb +1 -1
- data/spec/change_spec.rb +50 -50
- data/spec/diff_spec.rb +14 -14
- data/spec/hunk_spec.rb +19 -19
- data/spec/issues_spec.rb +48 -42
- data/spec/lcs_spec.rb +11 -11
- data/spec/ldiff_spec.rb +13 -11
- data/spec/patch_spec.rb +84 -84
- data/spec/sdiff_spec.rb +111 -109
- data/spec/spec_helper.rb +76 -74
- data/spec/traverse_balanced_spec.rb +191 -189
- data/spec/traverse_sequences_spec.rb +31 -31
- metadata +28 -21
data/lib/diff/lcs/change.rb
CHANGED
@@ -10,7 +10,7 @@ class Diff::LCS::Change
|
|
10
10
|
# (no change), '!' (changed), '<' (tail changes from first sequence), or
|
11
11
|
# '>' (tail changes from second sequence). The last two ('<>') are only
|
12
12
|
# found with Diff::LCS::diff and Diff::LCS::sdiff.
|
13
|
-
VALID_ACTIONS = %w
|
13
|
+
VALID_ACTIONS = %w[+ - = ! > <].freeze
|
14
14
|
|
15
15
|
def self.valid_action?(action)
|
16
16
|
VALID_ACTIONS.include? action
|
@@ -28,7 +28,7 @@ class Diff::LCS::Change
|
|
28
28
|
@action, @position, @element = *args
|
29
29
|
|
30
30
|
fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
|
31
|
-
fail
|
31
|
+
fail "Invalid Position Type" unless @position.is_a? IntClass
|
32
32
|
end
|
33
33
|
|
34
34
|
def inspect(*_args)
|
@@ -39,7 +39,7 @@ class Diff::LCS::Change
|
|
39
39
|
[@action, @position, @element]
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
alias_method :to_ary, :to_a
|
43
43
|
|
44
44
|
def self.from_a(arr)
|
45
45
|
arr = arr.flatten(1)
|
@@ -49,7 +49,7 @@ class Diff::LCS::Change
|
|
49
49
|
when 3
|
50
50
|
Diff::LCS::Change.new(*(arr[0...3]))
|
51
51
|
else
|
52
|
-
fail
|
52
|
+
fail "Invalid change array format provided."
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -70,27 +70,27 @@ class Diff::LCS::Change
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def adding?
|
73
|
-
@action ==
|
73
|
+
@action == "+"
|
74
74
|
end
|
75
75
|
|
76
76
|
def deleting?
|
77
|
-
@action ==
|
77
|
+
@action == "-"
|
78
78
|
end
|
79
79
|
|
80
80
|
def unchanged?
|
81
|
-
@action ==
|
81
|
+
@action == "="
|
82
82
|
end
|
83
83
|
|
84
84
|
def changed?
|
85
|
-
@action ==
|
85
|
+
@action == "!"
|
86
86
|
end
|
87
87
|
|
88
88
|
def finished_a?
|
89
|
-
@action ==
|
89
|
+
@action == ">"
|
90
90
|
end
|
91
91
|
|
92
92
|
def finished_b?
|
93
|
-
@action ==
|
93
|
+
@action == "<"
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -115,8 +115,8 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
115
115
|
@action, @old_position, @old_element, @new_position, @new_element = *args
|
116
116
|
|
117
117
|
fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
|
118
|
-
fail
|
119
|
-
fail
|
118
|
+
fail "Invalid (Old) Position Type" unless @old_position.nil? || @old_position.is_a?(IntClass)
|
119
|
+
fail "Invalid (New) Position Type" unless @new_position.nil? || @new_position.is_a?(IntClass)
|
120
120
|
end
|
121
121
|
|
122
122
|
def to_a
|
@@ -127,7 +127,7 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
127
127
|
]
|
128
128
|
end
|
129
129
|
|
130
|
-
|
130
|
+
alias_method :to_ary, :to_a
|
131
131
|
|
132
132
|
def self.from_a(arr)
|
133
133
|
Diff::LCS::Change.from_a(arr)
|
@@ -139,15 +139,15 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
139
139
|
ea = event.to_a
|
140
140
|
|
141
141
|
case ea[0]
|
142
|
-
when
|
142
|
+
when "-"
|
143
143
|
ea[2][1] = nil
|
144
|
-
when
|
145
|
-
ea[0] =
|
144
|
+
when "<"
|
145
|
+
ea[0] = "-"
|
146
146
|
ea[2][1] = nil
|
147
|
-
when
|
147
|
+
when "+"
|
148
148
|
ea[1][1] = nil
|
149
|
-
when
|
150
|
-
ea[0] =
|
149
|
+
when ">"
|
150
|
+
ea[0] = "+"
|
151
151
|
ea[1][1] = nil
|
152
152
|
end
|
153
153
|
|
data/lib/diff/lcs/htmldiff.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "cgi"
|
4
4
|
|
5
5
|
# Produce a simple HTML diff view.
|
6
6
|
class Diff::LCS::HTMLDiff
|
7
7
|
class << self
|
8
|
-
attr_accessor :can_expand_tabs
|
8
|
+
attr_accessor :can_expand_tabs # :nodoc:
|
9
9
|
end
|
10
10
|
self.can_expand_tabs = true
|
11
11
|
|
12
|
-
class Callbacks
|
12
|
+
class Callbacks # :nodoc:
|
13
13
|
attr_accessor :output
|
14
14
|
attr_accessor :match_class
|
15
15
|
attr_accessor :only_a_class
|
@@ -19,14 +19,14 @@ class Diff::LCS::HTMLDiff
|
|
19
19
|
@output = output
|
20
20
|
options ||= {}
|
21
21
|
|
22
|
-
@match_class = options[:match_class] ||
|
23
|
-
@only_a_class = options[:only_a_class] ||
|
24
|
-
@only_b_class = options[:only_b_class] ||
|
22
|
+
@match_class = options[:match_class] || "match"
|
23
|
+
@only_a_class = options[:only_a_class] || "only_a"
|
24
|
+
@only_b_class = options[:only_b_class] || "only_b"
|
25
25
|
end
|
26
26
|
|
27
27
|
def htmlize(element, css_class)
|
28
|
-
element =
|
29
|
-
%
|
28
|
+
element = " " if element.empty?
|
29
|
+
%(<pre class="#{__send__(css_class)}">#{element}</pre>\n)
|
30
30
|
end
|
31
31
|
private :htmlize
|
32
32
|
|
@@ -46,13 +46,16 @@ class Diff::LCS::HTMLDiff
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
# standard:disable Style/HashSyntax
|
49
50
|
DEFAULT_OPTIONS = {
|
50
51
|
:expand_tabs => nil,
|
51
52
|
:output => nil,
|
52
53
|
:css => nil,
|
53
54
|
:title => nil
|
54
55
|
}.freeze
|
56
|
+
# standard:enable Style/HashSyntax
|
55
57
|
|
58
|
+
# standard:disable Layout/HeredocIndentation
|
56
59
|
DEFAULT_CSS = <<-CSS
|
57
60
|
body { margin: 0; }
|
58
61
|
.diff
|
@@ -86,11 +89,12 @@ pre
|
|
86
89
|
}
|
87
90
|
h1 { margin-left: 2em; }
|
88
91
|
CSS
|
92
|
+
# standard:enable Layout/HeredocIndentation
|
89
93
|
|
90
94
|
def initialize(left, right, options = nil)
|
91
|
-
@left
|
92
|
-
@right
|
93
|
-
@options
|
95
|
+
@left = left
|
96
|
+
@right = right
|
97
|
+
@options = options
|
94
98
|
|
95
99
|
@options = DEFAULT_OPTIONS.dup if @options.nil?
|
96
100
|
end
|
@@ -103,7 +107,7 @@ h1 { margin-left: 2em; }
|
|
103
107
|
|
104
108
|
@options[:css] ||= DEFAULT_CSS.dup
|
105
109
|
|
106
|
-
@options[:title] ||=
|
110
|
+
@options[:title] ||= "diff"
|
107
111
|
end
|
108
112
|
private :verify_options
|
109
113
|
|
@@ -116,13 +120,14 @@ h1 { margin-left: 2em; }
|
|
116
120
|
formatter = Text::Format.new
|
117
121
|
formatter.tabstop = @options[:expand_tabs]
|
118
122
|
|
119
|
-
@left.map!
|
120
|
-
@right.map!
|
123
|
+
@left.map! { |line| formatter.expand(line.chomp) }
|
124
|
+
@right.map! { |line| formatter.expand(line.chomp) }
|
121
125
|
end
|
122
126
|
|
123
|
-
@left.map!
|
124
|
-
@right.map!
|
127
|
+
@left.map! { |line| CGI.escapeHTML(line.chomp) }
|
128
|
+
@right.map! { |line| CGI.escapeHTML(line.chomp) }
|
125
129
|
|
130
|
+
# standard:disable Layout/HeredocIndentation
|
126
131
|
@options[:output] << <<-OUTPUT
|
127
132
|
<html>
|
128
133
|
<head>
|
@@ -137,14 +142,17 @@ h1 { margin-left: 2em; }
|
|
137
142
|
<span class="only_b">Only in New</span></p>
|
138
143
|
<div class="diff">
|
139
144
|
OUTPUT
|
145
|
+
# standard:enable Layout/HeredocIndentation
|
140
146
|
|
141
147
|
callbacks = Callbacks.new(@options[:output])
|
142
148
|
Diff::LCS.traverse_sequences(@left, @right, callbacks)
|
143
149
|
|
150
|
+
# standard:disable Layout/HeredocIndentation
|
144
151
|
@options[:output] << <<-OUTPUT
|
145
152
|
</div>
|
146
153
|
</body>
|
147
154
|
</html>
|
148
155
|
OUTPUT
|
156
|
+
# standard:enable Layout/HeredocIndentation
|
149
157
|
end
|
150
158
|
end
|
data/lib/diff/lcs/hunk.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "diff/lcs/block"
|
4
4
|
|
5
5
|
# A Hunk is a group of Blocks which overlap because of the context surrounding
|
6
6
|
# each block. (So if we're not using context, every hunk will contain one
|
7
7
|
# block.) Used in the diff program (bin/ldiff).
|
8
8
|
class Diff::LCS::Hunk
|
9
|
-
OLD_DIFF_OP_ACTION = {
|
10
|
-
ED_DIFF_OP_ACTION = {
|
9
|
+
OLD_DIFF_OP_ACTION = {"+" => "a", "-" => "d", "!" => "c"}.freeze # :nodoc:
|
10
|
+
ED_DIFF_OP_ACTION = {"+" => "a", "-" => "d", "!" => "c"}.freeze # :nodoc:
|
11
11
|
|
12
12
|
private_constant :OLD_DIFF_OP_ACTION, :ED_DIFF_OP_ACTION if respond_to?(:private_constant)
|
13
13
|
|
@@ -22,7 +22,7 @@ class Diff::LCS::Hunk
|
|
22
22
|
end
|
23
23
|
|
24
24
|
if String.method_defined?(:encoding)
|
25
|
-
@preferred_data_encoding = data_old.fetch(0
|
25
|
+
@preferred_data_encoding = data_old.fetch(0) { data_new.fetch(0, "") }.encoding
|
26
26
|
end
|
27
27
|
|
28
28
|
@data_old = data_old
|
@@ -33,7 +33,6 @@ class Diff::LCS::Hunk
|
|
33
33
|
@file_length_difference = after # The caller must get this manually
|
34
34
|
@max_diff_size = @blocks.map { |e| e.diff_size.abs }.max
|
35
35
|
|
36
|
-
|
37
36
|
# Save the start & end of each array. If the array doesn't exist (e.g.,
|
38
37
|
# we're only adding items in this block), then figure out the line number
|
39
38
|
# based on the line number of the other file and the current difference in
|
@@ -54,8 +53,8 @@ class Diff::LCS::Hunk
|
|
54
53
|
|
55
54
|
@start_old = a1 || (b1 - before)
|
56
55
|
@start_new = b1 || (a1 + before)
|
57
|
-
@end_old
|
58
|
-
@end_new
|
56
|
+
@end_old = a2 || (b2 - after)
|
57
|
+
@end_new = b2 || (a2 + after)
|
59
58
|
|
60
59
|
self.flag_context = flag_context
|
61
60
|
end
|
@@ -67,12 +66,12 @@ class Diff::LCS::Hunk
|
|
67
66
|
|
68
67
|
# Change the "start" and "end" fields to note that context should be added
|
69
68
|
# to this hunk.
|
70
|
-
attr_accessor :flag_context
|
69
|
+
attr_accessor :flag_context
|
71
70
|
undef :flag_context=
|
72
|
-
def flag_context=(context)
|
73
|
-
return if context.nil?
|
71
|
+
def flag_context=(context) # :nodoc: # standard:disable Lint/DuplicateMethods
|
72
|
+
return if context.nil? || context.zero?
|
74
73
|
|
75
|
-
add_start = context > @start_old ? @start_old : context
|
74
|
+
add_start = (context > @start_old) ? @start_old : context
|
76
75
|
|
77
76
|
@start_old -= add_start
|
78
77
|
@start_new -= add_start
|
@@ -102,7 +101,7 @@ class Diff::LCS::Hunk
|
|
102
101
|
@start_new = hunk.start_new
|
103
102
|
blocks.unshift(*hunk.blocks)
|
104
103
|
end
|
105
|
-
|
104
|
+
alias_method :unshift, :merge
|
106
105
|
|
107
106
|
# Determines whether there is an overlap between this hunk and the
|
108
107
|
# provided hunk. This will be true if the difference between the two hunks
|
@@ -133,24 +132,24 @@ class Diff::LCS::Hunk
|
|
133
132
|
# Note that an old diff can't have any context. Therefore, we know that
|
134
133
|
# there's only one block in the hunk.
|
135
134
|
def old_diff(_last = false)
|
136
|
-
warn
|
135
|
+
warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1
|
137
136
|
|
138
137
|
block = @blocks[0]
|
139
138
|
|
140
139
|
# Calculate item number range. Old diff range is just like a context
|
141
140
|
# diff range, except the ranges are on one line with the action between
|
142
141
|
# them.
|
143
|
-
s = encode("#{context_range(:old,
|
142
|
+
s = encode("#{context_range(:old, ",")}#{OLD_DIFF_OP_ACTION[block.op]}#{context_range(:new, ",")}\n")
|
144
143
|
# If removing anything, just print out all the remove lines in the hunk
|
145
144
|
# which is just all the remove lines in the block.
|
146
145
|
unless block.remove.empty?
|
147
|
-
@data_old[@start_old..@end_old].each { |e| s << encode(
|
146
|
+
@data_old[@start_old..@end_old].each { |e| s << encode("< ") + e.chomp + encode("\n") }
|
148
147
|
end
|
149
148
|
|
150
|
-
s << encode("---\n") if block.op ==
|
149
|
+
s << encode("---\n") if block.op == "!"
|
151
150
|
|
152
151
|
unless block.insert.empty?
|
153
|
-
@data_new[@start_new..@end_new].each { |e| s << encode(
|
152
|
+
@data_new[@start_new..@end_new].each { |e| s << encode("> ") + e.chomp + encode("\n") }
|
154
153
|
end
|
155
154
|
|
156
155
|
s
|
@@ -172,7 +171,9 @@ class Diff::LCS::Hunk
|
|
172
171
|
# file -- don't take removed items into account.
|
173
172
|
lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0
|
174
173
|
|
175
|
-
|
174
|
+
# standard:disable Performance/UnfreezeString
|
175
|
+
outlist = @data_old[lo..hi].map { |e| String.new("#{encode(" ")}#{e.chomp}") }
|
176
|
+
# standard:enable Performance/UnfreezeString
|
176
177
|
|
177
178
|
last_block = blocks[-1]
|
178
179
|
|
@@ -183,7 +184,7 @@ class Diff::LCS::Hunk
|
|
183
184
|
|
184
185
|
@blocks.each do |block|
|
185
186
|
block.remove.each do |item|
|
186
|
-
op
|
187
|
+
op = item.action.to_s # -
|
187
188
|
offset = item.position - lo + num_added
|
188
189
|
outlist[offset][0, 1] = encode(op)
|
189
190
|
num_removed += 1
|
@@ -195,7 +196,7 @@ class Diff::LCS::Hunk
|
|
195
196
|
end
|
196
197
|
|
197
198
|
block.insert.each do |item|
|
198
|
-
op
|
199
|
+
op = item.action.to_s # +
|
199
200
|
offset = item.position - @start_new + num_removed
|
200
201
|
outlist[offset, 0] = encode(op) + @data_new[item.position].chomp
|
201
202
|
num_added += 1
|
@@ -212,8 +213,8 @@ class Diff::LCS::Hunk
|
|
212
213
|
|
213
214
|
def context_diff(last = false)
|
214
215
|
s = encode("***************\n")
|
215
|
-
s << encode("*** #{context_range(:old,
|
216
|
-
r = context_range(:new,
|
216
|
+
s << encode("*** #{context_range(:old, ",", last)} ****\n")
|
217
|
+
r = context_range(:new, ",", last)
|
217
218
|
|
218
219
|
if last
|
219
220
|
old_missing_newline = missing_last_newline?(@data_old)
|
@@ -226,7 +227,9 @@ class Diff::LCS::Hunk
|
|
226
227
|
removes = @blocks.reject { |e| e.remove.empty? }
|
227
228
|
|
228
229
|
unless removes.empty?
|
229
|
-
|
230
|
+
# standard:disable Performance/UnfreezeString
|
231
|
+
outlist = @data_old[lo..hi].map { |e| String.new("#{encode(" ")}#{e.chomp}") }
|
232
|
+
# standard:enable Performance/UnfreezeString
|
230
233
|
|
231
234
|
last_block = removes[-1]
|
232
235
|
|
@@ -248,7 +251,9 @@ class Diff::LCS::Hunk
|
|
248
251
|
inserts = @blocks.reject { |e| e.insert.empty? }
|
249
252
|
|
250
253
|
unless inserts.empty?
|
251
|
-
|
254
|
+
# standard:disable Performance/UnfreezeString
|
255
|
+
outlist = @data_new[lo..hi].map { |e| String.new("#{encode(" ")}#{e.chomp}") }
|
256
|
+
# standard:enable Performance/UnfreezeString
|
252
257
|
|
253
258
|
last_block = inserts[-1]
|
254
259
|
|
@@ -269,13 +274,13 @@ class Diff::LCS::Hunk
|
|
269
274
|
private :context_diff
|
270
275
|
|
271
276
|
def ed_diff(format, _last = false)
|
272
|
-
warn
|
277
|
+
warn "Expecting only one block in an old diff hunk!" if @blocks.size > 1
|
273
278
|
|
274
279
|
s =
|
275
280
|
if format == :reverse_ed
|
276
|
-
encode("#{ED_DIFF_OP_ACTION[@blocks[0].op]}#{context_range(:old,
|
281
|
+
encode("#{ED_DIFF_OP_ACTION[@blocks[0].op]}#{context_range(:old, ",")}\n")
|
277
282
|
else
|
278
|
-
encode("#{context_range(:old,
|
283
|
+
encode("#{context_range(:old, " ")}#{ED_DIFF_OP_ACTION[@blocks[0].op]}\n")
|
279
284
|
end
|
280
285
|
|
281
286
|
unless @blocks[0].insert.empty?
|
@@ -301,7 +306,7 @@ class Diff::LCS::Hunk
|
|
301
306
|
e -= 1 if last
|
302
307
|
e = 1 if e.zero?
|
303
308
|
|
304
|
-
s < e ? "#{s}#{op}#{e}" : e.to_s
|
309
|
+
(s < e) ? "#{s}#{op}#{e}" : e.to_s
|
305
310
|
end
|
306
311
|
private :context_range
|
307
312
|
|
@@ -318,8 +323,8 @@ class Diff::LCS::Hunk
|
|
318
323
|
|
319
324
|
length = e - s + (last ? 0 : 1)
|
320
325
|
|
321
|
-
first = length < 2 ? e : s # "strange, but correct"
|
322
|
-
length <= 1 ? first.to_s : "#{first},#{length}"
|
326
|
+
first = (length < 2) ? e : s # "strange, but correct"
|
327
|
+
(length <= 1) ? first.to_s : "#{first},#{length}"
|
323
328
|
end
|
324
329
|
private :unified_range
|
325
330
|
|
data/lib/diff/lcs/internals.rb
CHANGED
@@ -13,7 +13,7 @@ class << Diff::LCS
|
|
13
13
|
|
14
14
|
if block
|
15
15
|
callbacks.diffs.map do |hunk|
|
16
|
-
if hunk.
|
16
|
+
if hunk.is_a? Array
|
17
17
|
hunk.map { |hunk_block| block[hunk_block] }
|
18
18
|
else
|
19
19
|
block[hunk]
|
@@ -45,14 +45,14 @@ class << Diff::LCS::Internals
|
|
45
45
|
vector = []
|
46
46
|
|
47
47
|
# Collect any common elements at the beginning...
|
48
|
-
while (a_start <= a_finish)
|
48
|
+
while (a_start <= a_finish) && (b_start <= b_finish) && (a[a_start] == b[b_start])
|
49
49
|
vector[a_start] = b_start
|
50
50
|
a_start += 1
|
51
51
|
b_start += 1
|
52
52
|
end
|
53
53
|
|
54
54
|
# Now the end...
|
55
|
-
while (a_start <= a_finish)
|
55
|
+
while (a_start <= a_finish) && (b_start <= b_finish) && (a[a_finish] == b[b_finish])
|
56
56
|
vector[a_finish] = b_finish
|
57
57
|
a_finish -= 1
|
58
58
|
b_finish -= 1
|
@@ -63,8 +63,8 @@ class << Diff::LCS::Internals
|
|
63
63
|
b_matches = position_hash(b, b_start..b_finish)
|
64
64
|
|
65
65
|
thresh = []
|
66
|
-
links
|
67
|
-
string = a.
|
66
|
+
links = []
|
67
|
+
string = a.is_a?(String)
|
68
68
|
|
69
69
|
(a_start..a_finish).each do |i|
|
70
70
|
ai = string ? a[i, 1] : a[i]
|
@@ -75,7 +75,7 @@ class << Diff::LCS::Internals
|
|
75
75
|
# it may have an optimization purpose
|
76
76
|
# An attempt to remove it: https://github.com/halostatue/diff-lcs/pull/72
|
77
77
|
# Why it is reintroduced: https://github.com/halostatue/diff-lcs/issues/78
|
78
|
-
if k
|
78
|
+
if k && (thresh[k] > j) && (thresh[k - 1] < j)
|
79
79
|
thresh[k] = j
|
80
80
|
else
|
81
81
|
k = replace_next_larger(thresh, j, k)
|
@@ -100,7 +100,7 @@ class << Diff::LCS::Internals
|
|
100
100
|
# the object form of same) and detection of whether the patchset represents
|
101
101
|
# changes to be made.
|
102
102
|
def analyze_patchset(patchset, depth = 0)
|
103
|
-
fail
|
103
|
+
fail "Patchset too complex" if depth > 1
|
104
104
|
|
105
105
|
has_changes = false
|
106
106
|
new_patchset = []
|
@@ -145,7 +145,7 @@ class << Diff::LCS::Internals
|
|
145
145
|
# Diff::LCS::Change as its source, as an array will cause the creation
|
146
146
|
# of one of the above.
|
147
147
|
def intuit_diff_direction(src, patchset, limit = nil)
|
148
|
-
string = src.
|
148
|
+
string = src.is_a?(String)
|
149
149
|
count = left_match = left_miss = right_match = right_miss = 0
|
150
150
|
|
151
151
|
patchset.each do |change|
|
@@ -157,22 +157,22 @@ class << Diff::LCS::Internals
|
|
157
157
|
re = string ? src[change.new_position, 1] : src[change.new_position]
|
158
158
|
|
159
159
|
case change.action
|
160
|
-
when
|
160
|
+
when "-" # Remove details from the old string
|
161
161
|
if le == change.old_element
|
162
162
|
left_match += 1
|
163
163
|
else
|
164
164
|
left_miss += 1
|
165
165
|
end
|
166
|
-
when
|
166
|
+
when "+"
|
167
167
|
if re == change.new_element
|
168
168
|
right_match += 1
|
169
169
|
else
|
170
170
|
right_miss += 1
|
171
171
|
end
|
172
|
-
when
|
172
|
+
when "="
|
173
173
|
left_miss += 1 if le != change.old_element
|
174
174
|
right_miss += 1 if re != change.new_element
|
175
|
-
when
|
175
|
+
when "!"
|
176
176
|
if le == change.old_element
|
177
177
|
left_match += 1
|
178
178
|
elsif re == change.new_element
|
@@ -189,19 +189,19 @@ class << Diff::LCS::Internals
|
|
189
189
|
element = string ? src[change.position, 1] : src[change.position]
|
190
190
|
|
191
191
|
case change.action
|
192
|
-
when
|
192
|
+
when "-"
|
193
193
|
if element == change.element
|
194
194
|
left_match += 1
|
195
195
|
else
|
196
196
|
left_miss += 1
|
197
197
|
end
|
198
|
-
when
|
198
|
+
when "+"
|
199
199
|
if element == change.element
|
200
200
|
right_match += 1
|
201
201
|
else
|
202
202
|
right_miss += 1
|
203
203
|
end
|
204
|
-
when
|
204
|
+
when "="
|
205
205
|
if element != change.element
|
206
206
|
left_miss += 1
|
207
207
|
right_miss += 1
|
@@ -251,7 +251,7 @@ enumerable as either source or destination value."
|
|
251
251
|
# This operation preserves the sort order.
|
252
252
|
def replace_next_larger(enum, value, last_index = nil)
|
253
253
|
# Off the end?
|
254
|
-
if enum.empty?
|
254
|
+
if enum.empty? || (value > enum[-1])
|
255
255
|
enum << value
|
256
256
|
return enum.size - 1
|
257
257
|
end
|
@@ -296,7 +296,7 @@ enumerable as either source or destination value."
|
|
296
296
|
# positions it occupies in the Enumerable, optionally restricted to the
|
297
297
|
# elements specified in the range of indexes specified by +interval+.
|
298
298
|
def position_hash(enum, interval)
|
299
|
-
string = enum.
|
299
|
+
string = enum.is_a?(String)
|
300
300
|
hash = Hash.new { |h, k| h[k] = [] }
|
301
301
|
interval.each do |i|
|
302
302
|
k = string ? enum[i, 1] : enum[i]
|