diff-lcs 1.2.5 → 1.4.3

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.
Files changed (55) hide show
  1. checksums.yaml +6 -14
  2. data/.rspec +0 -1
  3. data/Code-of-Conduct.md +74 -0
  4. data/Contributing.md +84 -0
  5. data/History.md +278 -0
  6. data/{License.rdoc → License.md} +0 -0
  7. data/Manifest.txt +15 -8
  8. data/README.rdoc +18 -19
  9. data/Rakefile +41 -25
  10. data/autotest/discover.rb +3 -1
  11. data/bin/htmldiff +7 -4
  12. data/bin/ldiff +4 -1
  13. data/lib/diff-lcs.rb +1 -1
  14. data/lib/diff/lcs.rb +181 -254
  15. data/lib/diff/lcs/array.rb +1 -1
  16. data/lib/diff/lcs/backports.rb +9 -0
  17. data/lib/diff/lcs/block.rb +2 -2
  18. data/lib/diff/lcs/callbacks.rb +15 -12
  19. data/lib/diff/lcs/change.rb +33 -36
  20. data/lib/diff/lcs/htmldiff.rb +17 -16
  21. data/lib/diff/lcs/hunk.rb +67 -52
  22. data/lib/diff/lcs/internals.rb +43 -40
  23. data/lib/diff/lcs/ldiff.rb +44 -64
  24. data/lib/diff/lcs/string.rb +1 -1
  25. data/spec/change_spec.rb +31 -7
  26. data/spec/diff_spec.rb +24 -20
  27. data/spec/fixtures/aX +1 -0
  28. data/spec/fixtures/bXaX +1 -0
  29. data/spec/fixtures/ds1.csv +50 -0
  30. data/spec/fixtures/ds2.csv +51 -0
  31. data/spec/fixtures/ldiff/output.diff +4 -0
  32. data/spec/fixtures/ldiff/output.diff-c +7 -0
  33. data/spec/fixtures/ldiff/output.diff-e +3 -0
  34. data/spec/fixtures/ldiff/output.diff-f +3 -0
  35. data/spec/fixtures/ldiff/output.diff-u +5 -0
  36. data/spec/hunk_spec.rb +37 -37
  37. data/spec/issues_spec.rb +91 -17
  38. data/spec/lcs_spec.rb +24 -22
  39. data/spec/ldiff_spec.rb +86 -0
  40. data/spec/patch_spec.rb +182 -180
  41. data/spec/sdiff_spec.rb +91 -91
  42. data/spec/spec_helper.rb +143 -58
  43. data/spec/traverse_balanced_spec.rb +177 -177
  44. data/spec/traverse_sequences_spec.rb +63 -63
  45. metadata +87 -143
  46. checksums.yaml.gz.sig +0 -0
  47. data.tar.gz.sig +0 -3
  48. data/.autotest +0 -3
  49. data/.gemtest +0 -0
  50. data/.hoerc +0 -2
  51. data/.travis.yml +0 -22
  52. data/Contributing.rdoc +0 -64
  53. data/Gemfile +0 -20
  54. data/History.rdoc +0 -152
  55. metadata.gz.sig +0 -2
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  class << Diff::LCS
4
4
  def diff_traversal(method, seq1, seq2, callbacks, &block)
@@ -45,8 +45,7 @@ class << Diff::LCS::Internals
45
45
  vector = []
46
46
 
47
47
  # Prune off any common elements at the beginning...
48
- while ((a_start <= a_finish) and (b_start <= b_finish) and
49
- (a[a_start] == b[b_start]))
48
+ while (a_start <= a_finish) and (b_start <= b_finish) and (a[a_start] == b[b_start])
50
49
  vector[a_start] = b_start
51
50
  a_start += 1
52
51
  b_start += 1
@@ -54,8 +53,7 @@ class << Diff::LCS::Internals
54
53
  b_start = a_start
55
54
 
56
55
  # Now the end...
57
- while ((a_start <= a_finish) and (b_start <= b_finish) and
58
- (a[a_finish] == b[b_finish]))
56
+ while (a_start <= a_finish) and (b_start <= b_finish) and (a[a_finish] == b[b_finish])
59
57
  vector[a_finish] = b_finish
60
58
  a_finish -= 1
61
59
  b_finish -= 1
@@ -68,7 +66,7 @@ class << Diff::LCS::Internals
68
66
  links = []
69
67
  string = a.kind_of?(String)
70
68
 
71
- (a_start .. a_finish).each do |i|
69
+ (a_start..a_finish).each do |i|
72
70
  ai = string ? a[i, 1] : a[i]
73
71
  bm = b_matches[ai]
74
72
  k = nil
@@ -78,13 +76,13 @@ class << Diff::LCS::Internals
78
76
  else
79
77
  k = replace_next_larger(thresh, j, k)
80
78
  end
81
- links[k] = [ (k > 0) ? links[k - 1] : nil, i, j ] unless k.nil?
79
+ links[k] = [k.positive? ? links[k - 1] : nil, i, j] unless k.nil?
82
80
  end
83
81
  end
84
82
 
85
83
  unless thresh.empty?
86
84
  link = links[thresh.size - 1]
87
- while not link.nil?
85
+ until link.nil?
88
86
  vector[link[1]] = link[2]
89
87
  link = link[0]
90
88
  end
@@ -93,14 +91,15 @@ class << Diff::LCS::Internals
93
91
  vector
94
92
  end
95
93
 
96
- # This method will analyze the provided patchset to provide a
97
- # single-pass normalization (conversion of the array form of
98
- # Diff::LCS::Change objects to the object form of same) and detection of
99
- # whether the patchset represents changes to be made.
94
+ # This method will analyze the provided patchset to provide a single-pass
95
+ # normalization (conversion of the array form of Diff::LCS::Change objects to
96
+ # the object form of same) and detection of whether the patchset represents
97
+ # changes to be made.
100
98
  def analyze_patchset(patchset, depth = 0)
101
- raise "Patchset too complex" if depth > 1
99
+ fail 'Patchset too complex' if depth > 1
102
100
 
103
101
  has_changes = false
102
+ new_patchset = []
104
103
 
105
104
  # Format:
106
105
  # [ # patchset
@@ -110,29 +109,28 @@ class << Diff::LCS::Internals
110
109
  # ]
111
110
  # ]
112
111
 
113
- patchset = patchset.map do |hunk|
112
+ patchset.each do |hunk|
114
113
  case hunk
115
114
  when Diff::LCS::Change
116
115
  has_changes ||= !hunk.unchanged?
117
- hunk
116
+ new_patchset << hunk
118
117
  when Array
119
- # Detect if the 'hunk' is actually an array-format
120
- # Change object.
118
+ # Detect if the 'hunk' is actually an array-format change object.
121
119
  if Diff::LCS::Change.valid_action? hunk[0]
122
120
  hunk = Diff::LCS::Change.from_a(hunk)
123
121
  has_changes ||= !hunk.unchanged?
124
- hunk
122
+ new_patchset << hunk
125
123
  else
126
124
  with_changes, hunk = analyze_patchset(hunk, depth + 1)
127
125
  has_changes ||= with_changes
128
- hunk.flatten
126
+ new_patchset.concat(hunk)
129
127
  end
130
128
  else
131
- raise ArgumentError, "Cannot normalise a hunk of class #{hunk.class}."
129
+ fail ArgumentError, "Cannot normalise a hunk of class #{hunk.class}."
132
130
  end
133
131
  end
134
132
 
135
- [ has_changes, patchset.flatten(1) ]
133
+ [has_changes, new_patchset]
136
134
  end
137
135
 
138
136
  # Examine the patchset and the source to see in which direction the
@@ -142,8 +140,6 @@ class << Diff::LCS::Internals
142
140
  # some time. This also works better with Diff::LCS::ContextChange or
143
141
  # Diff::LCS::Change as its source, as an array will cause the creation
144
142
  # of one of the above.
145
- #
146
- # Note: This will be deprecated as a public function in a future release.
147
143
  def intuit_diff_direction(src, patchset, limit = nil)
148
144
  string = src.kind_of?(String)
149
145
  count = left_match = left_miss = right_match = right_miss = 0
@@ -175,13 +171,11 @@ class << Diff::LCS::Internals
175
171
  when '!'
176
172
  if le == change.old_element
177
173
  left_match += 1
174
+ elsif re == change.new_element
175
+ right_match += 1
178
176
  else
179
- if re == change.new_element
180
- right_match += 1
181
- else
182
- left_miss += 1
183
- right_miss += 1
184
- end
177
+ left_miss += 1
178
+ right_miss += 1
185
179
  end
186
180
  end
187
181
  when Diff::LCS::Change
@@ -211,11 +205,11 @@ class << Diff::LCS::Internals
211
205
  end
212
206
  end
213
207
 
214
- break if (not limit.nil?) && (count > limit)
208
+ break if !limit.nil? && (count > limit)
215
209
  end
216
210
 
217
- no_left = (left_match == 0) && (left_miss > 0)
218
- no_right = (right_match == 0) && (right_miss > 0)
211
+ no_left = left_match.zero? && left_miss.positive?
212
+ no_right = right_match.zero? && right_miss.positive?
219
213
 
220
214
  case [no_left, no_right]
221
215
  when [false, true]
@@ -225,11 +219,20 @@ class << Diff::LCS::Internals
225
219
  else
226
220
  case left_match <=> right_match
227
221
  when 1
228
- :patch
222
+ if left_miss.zero?
223
+ :patch
224
+ else
225
+ :unpatch
226
+ end
229
227
  when -1
230
- :unpatch
228
+ if right_miss.zero?
229
+ :unpatch
230
+ else
231
+ :patch
232
+ end
231
233
  else
232
- raise "The provided patchset does not appear to apply to the provided value as either source or destination value."
234
+ fail "The provided patchset does not appear to apply to the provided \
235
+ enumerable as either source or destination value."
233
236
  end
234
237
  end
235
238
  end
@@ -252,14 +255,14 @@ class << Diff::LCS::Internals
252
255
  # Binary search for the insertion point
253
256
  last_index ||= enum.size
254
257
  first_index = 0
255
- while (first_index <= last_index)
258
+ while first_index <= last_index
256
259
  i = (first_index + last_index) >> 1
257
260
 
258
261
  found = enum[i]
259
262
 
260
- if value == found
261
- return nil
262
- elsif value > found
263
+ return nil if value == found
264
+
265
+ if value > found
263
266
  first_index = i + 1
264
267
  else
265
268
  last_index = i - 1
@@ -269,7 +272,7 @@ class << Diff::LCS::Internals
269
272
  # The insertion point is in first_index; overwrite the next larger
270
273
  # value.
271
274
  enum[first_index] = value
272
- return first_index
275
+ first_index
273
276
  end
274
277
  private :replace_next_larger
275
278
 
@@ -1,49 +1,21 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
4
  require 'ostruct'
5
5
  require 'diff/lcs/hunk'
6
6
 
7
- # == ldiff Usage
8
- # ldiff [options] oldfile newfile
9
- #
10
- # -c:: Displays a context diff with 3 lines of context.
11
- # -C [LINES], --context [LINES]:: Displays a context diff with LINES lines of context. Default 3 lines.
12
- # -u:: Displays a unified diff with 3 lines of context.
13
- # -U [LINES], --unified [LINES]:: Displays a unified diff with LINES lines of context. Default 3 lines.
14
- # -e:: Creates an 'ed' script to change oldfile to newfile.
15
- # -f:: Creates an 'ed' script to change oldfile to newfile in reverse order.
16
- # -a, --text:: Treats the files as text and compares them line-by-line, even if they do not seem to be text.
17
- # --binary:: Treats the files as binary.
18
- # -q, --brief:: Reports only whether or not the files differ, not the details.
19
- # --help:: Shows the command-line help.
20
- # --version:: Shows the version of Diff::LCS.
21
- #
22
- # By default, runs produces an "old-style" diff, with output like UNIX diff.
23
- #
24
- # == Copyright
25
- # Copyright &copy; 2004 Austin Ziegler
26
- #
27
- # Part of Diff::LCS <http://rubyforge.org/projects/ruwiki/>
28
- # Austin Ziegler <diff-lcs@halostatue.ca>
29
- #
30
- # This program is free software. It may be redistributed and/or modified under
31
- # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
32
- # Ruby licence.
33
- module Diff::LCS::Ldiff
7
+ module Diff::LCS::Ldiff #:nodoc:
34
8
  BANNER = <<-COPYRIGHT
35
9
  ldiff #{Diff::LCS::VERSION}
36
- Copyright 2004-2013 Austin Ziegler
10
+ Copyright 2004-2019 Austin Ziegler
37
11
 
38
12
  Part of Diff::LCS.
39
- http://rubyforge.org/projects/ruwiki/
40
-
41
- Austin Ziegler <diff-lcs@halostatue.ca>
13
+ https://github.com/halostatue/diff-lcs
42
14
 
43
15
  This program is free software. It may be redistributed and/or modified under
44
16
  the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
45
17
  MIT licence.
46
- COPYRIGHT
18
+ COPYRIGHT
47
19
  end
48
20
 
49
21
  class << Diff::LCS::Ldiff
@@ -51,33 +23,42 @@ class << Diff::LCS::Ldiff
51
23
  attr_reader :file_old, :file_new #:nodoc:
52
24
  attr_reader :data_old, :data_new #:nodoc:
53
25
 
54
- def run(args, input = $stdin, output = $stdout, error = $stderr) #:nodoc:
26
+ def run(args, _input = $stdin, output = $stdout, error = $stderr) #:nodoc:
55
27
  @binary = nil
56
28
 
57
29
  args.options do |o|
58
30
  o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile"
59
- o.separator ""
60
- o.on('-c', '-C', '--context [LINES]', Numeric, 'Displays a context diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
31
+ o.separator ''
32
+ o.on(
33
+ '-c', '-C', '--context [LINES]', Integer,
34
+ 'Displays a context diff with LINES lines', 'of context. Default 3 lines.'
35
+ ) do |ctx|
61
36
  @format = :context
62
37
  @lines = ctx || 3
63
38
  end
64
- o.on('-u', '-U', '--unified [LINES]', Numeric, 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
39
+ o.on(
40
+ '-u', '-U', '--unified [LINES]', Integer,
41
+ 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.'
42
+ ) do |ctx|
65
43
  @format = :unified
66
44
  @lines = ctx || 3
67
45
  end
68
- o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |ctx|
46
+ o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |_ctx|
69
47
  @format = :ed
70
48
  end
71
- o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |ctx|
49
+ o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |_ctx|
72
50
  @format = :reverse_ed
73
51
  end
74
- o.on('-a', '--text', 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.') do |txt|
52
+ o.on(
53
+ '-a', '--text',
54
+ 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.'
55
+ ) do |_txt|
75
56
  @binary = false
76
57
  end
77
- o.on('--binary', 'Treats the files as binary.') do |bin|
58
+ o.on('--binary', 'Treats the files as binary.') do |_bin|
78
59
  @binary = true
79
60
  end
80
- o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |ctx|
61
+ o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |_ctx|
81
62
  @format = :report
82
63
  end
83
64
  o.on_tail('--help', 'Shows this text.') do
@@ -85,10 +66,10 @@ class << Diff::LCS::Ldiff
85
66
  return 0
86
67
  end
87
68
  o.on_tail('--version', 'Shows the version of Diff::LCS.') do
88
- error << BANNER
69
+ error << Diff::LCS::Ldiff::BANNER
89
70
  return 0
90
71
  end
91
- o.on_tail ""
72
+ o.on_tail ''
92
73
  o.on_tail 'By default, runs produces an "old-style" diff, with output like UNIX diff.'
93
74
  o.parse!
94
75
  end
@@ -118,15 +99,14 @@ class << Diff::LCS::Ldiff
118
99
  file_length_difference = 0
119
100
 
120
101
  if @binary.nil? or @binary
121
- data_old = IO::read(file_old)
122
- data_new = IO::read(file_new)
102
+ data_old = IO.read(file_old)
103
+ data_new = IO.read(file_new)
123
104
 
124
105
  # Test binary status
125
106
  if @binary.nil?
126
- old_txt = data_old[0...4096].scan(/\0/).empty?
127
- new_txt = data_new[0...4096].scan(/\0/).empty?
128
- @binary = (not old_txt) or (not new_txt)
129
- old_txt = new_txt = nil
107
+ old_txt = data_old[0, 4096].scan(/\0/).empty?
108
+ new_txt = data_new[0, 4096].scan(/\0/).empty?
109
+ @binary = !old_txt or !new_txt
130
110
  end
131
111
 
132
112
  unless @binary
@@ -134,8 +114,8 @@ class << Diff::LCS::Ldiff
134
114
  data_new = data_new.split($/).map { |e| e.chomp }
135
115
  end
136
116
  else
137
- data_old = IO::readlines(file_old).map { |e| e.chomp }
138
- data_new = IO::readlines(file_new).map { |e| e.chomp }
117
+ data_old = IO.readlines(file_old).map { |e| e.chomp }
118
+ data_new = IO.readlines(file_new).map { |e| e.chomp }
139
119
  end
140
120
 
141
121
  # diff yields lots of pieces, each of which is basically a Block object
@@ -154,10 +134,10 @@ class << Diff::LCS::Ldiff
154
134
  end
155
135
 
156
136
  if (@format == :unified) or (@format == :context)
157
- ft = File.stat(file_old).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
158
- puts "#{char_old} #{file_old}\t#{ft}"
159
- ft = File.stat(file_new).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
160
- puts "#{char_new} #{file_new}\t#{ft}"
137
+ ft = File.stat(file_old).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.000000000 %z')
138
+ output << "#{char_old} #{file_old}\t#{ft}\n"
139
+ ft = File.stat(file_new).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.000000000 %z')
140
+ output << "#{char_new} #{file_new}\t#{ft}\n"
161
141
  end
162
142
 
163
143
  # Loop over hunks. If a hunk overlaps with the last hunk, join them.
@@ -171,12 +151,11 @@ class << Diff::LCS::Ldiff
171
151
 
172
152
  diffs.each do |piece|
173
153
  begin
174
- hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines,
175
- file_length_difference)
154
+ hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines, file_length_difference)
176
155
  file_length_difference = hunk.file_length_difference
177
156
 
178
157
  next unless oldhunk
179
- next if (@lines > 0) and hunk.merge(oldhunk)
158
+ next if @lines.positive? and hunk.merge(oldhunk)
180
159
 
181
160
  output << oldhunk.diff(@format) << "\n"
182
161
  ensure
@@ -184,12 +163,13 @@ class << Diff::LCS::Ldiff
184
163
  end
185
164
  end
186
165
 
187
- output << oldhunk.diff(@format) << "\n"
166
+ last = oldhunk.diff(@format)
167
+ last << "\n" if last.respond_to?(:end_with?) && !last.end_with?("\n")
188
168
 
189
- if @format == :ed
190
- output.reverse_each { |e| real_output << e.diff(:ed_finish) }
191
- end
169
+ output << last
170
+
171
+ output.reverse_each { |e| real_output << e.diff(:ed_finish) } if @format == :ed
192
172
 
193
- return 1
173
+ 1
194
174
  end
195
175
  end
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  class String
4
4
  include Diff::LCS
@@ -1,9 +1,9 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Diff::LCS::Change do
6
- describe "an add" do
6
+ describe 'an add' do
7
7
  subject { described_class.new('+', 0, 'element') }
8
8
  it { should_not be_deleting }
9
9
  it { should be_adding }
@@ -13,7 +13,7 @@ describe Diff::LCS::Change do
13
13
  it { should_not be_finished_b }
14
14
  end
15
15
 
16
- describe "a delete" do
16
+ describe 'a delete' do
17
17
  subject { described_class.new('-', 0, 'element') }
18
18
  it { should be_deleting }
19
19
  it { should_not be_adding }
@@ -23,7 +23,7 @@ describe Diff::LCS::Change do
23
23
  it { should_not be_finished_b }
24
24
  end
25
25
 
26
- describe "an unchanged" do
26
+ describe 'an unchanged' do
27
27
  subject { described_class.new('=', 0, 'element') }
28
28
  it { should_not be_deleting }
29
29
  it { should_not be_adding }
@@ -33,7 +33,7 @@ describe Diff::LCS::Change do
33
33
  it { should_not be_finished_b }
34
34
  end
35
35
 
36
- describe "a changed" do
36
+ describe 'a changed' do
37
37
  subject { described_class.new('!', 0, 'element') }
38
38
  it { should_not be_deleting }
39
39
  it { should_not be_adding }
@@ -43,7 +43,7 @@ describe Diff::LCS::Change do
43
43
  it { should_not be_finished_b }
44
44
  end
45
45
 
46
- describe "a finished_a" do
46
+ describe 'a finished_a' do
47
47
  subject { described_class.new('>', 0, 'element') }
48
48
  it { should_not be_deleting }
49
49
  it { should_not be_adding }
@@ -53,7 +53,7 @@ describe Diff::LCS::Change do
53
53
  it { should_not be_finished_b }
54
54
  end
55
55
 
56
- describe "a finished_b" do
56
+ describe 'a finished_b' do
57
57
  subject { described_class.new('<', 0, 'element') }
58
58
  it { should_not be_deleting }
59
59
  it { should_not be_adding }
@@ -62,4 +62,28 @@ describe Diff::LCS::Change do
62
62
  it { should_not be_finished_a }
63
63
  it { should be_finished_b }
64
64
  end
65
+
66
+ describe 'as array' do
67
+ it 'should be converted' do
68
+ action, position, element = described_class.new('!', 0, 'element')
69
+ expect(action).to eq '!'
70
+ expect(position).to eq 0
71
+ expect(element).to eq 'element'
72
+ end
73
+ end
74
+ end
75
+
76
+ describe Diff::LCS::ContextChange do
77
+ describe 'as array' do
78
+ it 'should be converted' do
79
+ action, (old_position, old_element), (new_position, new_element) =
80
+ described_class.new('!', 1, 'old_element', 2, 'new_element')
81
+
82
+ expect(action).to eq '!'
83
+ expect(old_position).to eq 1
84
+ expect(old_element).to eq 'old_element'
85
+ expect(new_position).to eq 2
86
+ expect(new_element).to eq 'new_element'
87
+ end
88
+ end
65
89
  end