diff-lcs 1.2.2 → 1.4

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 +7 -0
  2. data/.rspec +0 -1
  3. data/Code-of-Conduct.md +74 -0
  4. data/Contributing.md +84 -0
  5. data/History.md +247 -0
  6. data/{License.rdoc → License.md} +0 -0
  7. data/Manifest.txt +15 -9
  8. data/README.rdoc +21 -18
  9. data/Rakefile +35 -23
  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 +1 -1
  18. data/lib/diff/lcs/callbacks.rb +15 -12
  19. data/lib/diff/lcs/change.rb +34 -37
  20. data/lib/diff/lcs/htmldiff.rb +17 -16
  21. data/lib/diff/lcs/hunk.rb +59 -47
  22. data/lib/diff/lcs/internals.rb +44 -40
  23. data/lib/diff/lcs/ldiff.rb +45 -65
  24. data/lib/diff/lcs/string.rb +1 -1
  25. data/spec/change_spec.rb +31 -7
  26. data/spec/diff_spec.rb +28 -18
  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 +54 -45
  37. data/spec/issues_spec.rb +50 -17
  38. data/spec/lcs_spec.rb +24 -22
  39. data/spec/ldiff_spec.rb +72 -0
  40. data/spec/patch_spec.rb +182 -180
  41. data/spec/sdiff_spec.rb +99 -87
  42. data/spec/spec_helper.rb +141 -58
  43. data/spec/traverse_balanced_spec.rb +177 -177
  44. data/spec/traverse_sequences_spec.rb +63 -63
  45. metadata +100 -169
  46. data.tar.gz.sig +0 -0
  47. data/.autotest +0 -3
  48. data/.gemtest +0 -0
  49. data/.hoerc +0 -2
  50. data/.travis.yml +0 -22
  51. data/Contributing.rdoc +0 -64
  52. data/Gemfile +0 -19
  53. data/History.rdoc +0 -117
  54. data/diff-lcs.gemspec +0 -63
  55. metadata.gz.sig +0 -4
@@ -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,16 +45,15 @@ 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
51
+ b_start += 1
52
52
  end
53
53
  b_start = a_start
54
54
 
55
55
  # Now the end...
56
- while ((a_start <= a_finish) and (b_start <= b_finish) and
57
- (a[a_finish] == b[b_finish]))
56
+ while (a_start <= a_finish) and (b_start <= b_finish) and (a[a_finish] == b[b_finish])
58
57
  vector[a_finish] = b_finish
59
58
  a_finish -= 1
60
59
  b_finish -= 1
@@ -67,7 +66,7 @@ class << Diff::LCS::Internals
67
66
  links = []
68
67
  string = a.kind_of?(String)
69
68
 
70
- (a_start .. a_finish).each do |i|
69
+ (a_start..a_finish).each do |i|
71
70
  ai = string ? a[i, 1] : a[i]
72
71
  bm = b_matches[ai]
73
72
  k = nil
@@ -77,13 +76,13 @@ class << Diff::LCS::Internals
77
76
  else
78
77
  k = replace_next_larger(thresh, j, k)
79
78
  end
80
- 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?
81
80
  end
82
81
  end
83
82
 
84
83
  unless thresh.empty?
85
84
  link = links[thresh.size - 1]
86
- while not link.nil?
85
+ until link.nil?
87
86
  vector[link[1]] = link[2]
88
87
  link = link[0]
89
88
  end
@@ -92,14 +91,15 @@ class << Diff::LCS::Internals
92
91
  vector
93
92
  end
94
93
 
95
- # This method will analyze the provided patchset to provide a
96
- # single-pass normalization (conversion of the array form of
97
- # Diff::LCS::Change objects to the object form of same) and detection of
98
- # 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.
99
98
  def analyze_patchset(patchset, depth = 0)
100
- raise "Patchset too complex" if depth > 1
99
+ fail 'Patchset too complex' if depth > 1
101
100
 
102
101
  has_changes = false
102
+ new_patchset = []
103
103
 
104
104
  # Format:
105
105
  # [ # patchset
@@ -109,29 +109,28 @@ class << Diff::LCS::Internals
109
109
  # ]
110
110
  # ]
111
111
 
112
- patchset = patchset.map do |hunk|
112
+ patchset.each do |hunk|
113
113
  case hunk
114
114
  when Diff::LCS::Change
115
115
  has_changes ||= !hunk.unchanged?
116
- hunk
116
+ new_patchset << hunk
117
117
  when Array
118
- # Detect if the 'hunk' is actually an array-format
119
- # Change object.
118
+ # Detect if the 'hunk' is actually an array-format change object.
120
119
  if Diff::LCS::Change.valid_action? hunk[0]
121
120
  hunk = Diff::LCS::Change.from_a(hunk)
122
121
  has_changes ||= !hunk.unchanged?
123
- hunk
122
+ new_patchset << hunk
124
123
  else
125
124
  with_changes, hunk = analyze_patchset(hunk, depth + 1)
126
125
  has_changes ||= with_changes
127
- hunk.flatten
126
+ new_patchset.concat(hunk)
128
127
  end
129
128
  else
130
- raise ArgumentError, "Cannot normalise a hunk of class #{hunk.class}."
129
+ fail ArgumentError, "Cannot normalise a hunk of class #{hunk.class}."
131
130
  end
132
131
  end
133
132
 
134
- [ has_changes, patchset.flatten(1) ]
133
+ [has_changes, new_patchset]
135
134
  end
136
135
 
137
136
  # Examine the patchset and the source to see in which direction the
@@ -141,8 +140,6 @@ class << Diff::LCS::Internals
141
140
  # some time. This also works better with Diff::LCS::ContextChange or
142
141
  # Diff::LCS::Change as its source, as an array will cause the creation
143
142
  # of one of the above.
144
- #
145
- # Note: This will be deprecated as a public function in a future release.
146
143
  def intuit_diff_direction(src, patchset, limit = nil)
147
144
  string = src.kind_of?(String)
148
145
  count = left_match = left_miss = right_match = right_miss = 0
@@ -174,13 +171,11 @@ class << Diff::LCS::Internals
174
171
  when '!'
175
172
  if le == change.old_element
176
173
  left_match += 1
174
+ elsif re == change.new_element
175
+ right_match += 1
177
176
  else
178
- if re == change.new_element
179
- right_match += 1
180
- else
181
- left_miss += 1
182
- right_miss += 1
183
- end
177
+ left_miss += 1
178
+ right_miss += 1
184
179
  end
185
180
  end
186
181
  when Diff::LCS::Change
@@ -210,11 +205,11 @@ class << Diff::LCS::Internals
210
205
  end
211
206
  end
212
207
 
213
- break if (not limit.nil?) && (count > limit)
208
+ break if !limit.nil? && (count > limit)
214
209
  end
215
210
 
216
- no_left = (left_match == 0) && (left_miss > 0)
217
- 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?
218
213
 
219
214
  case [no_left, no_right]
220
215
  when [false, true]
@@ -224,11 +219,20 @@ class << Diff::LCS::Internals
224
219
  else
225
220
  case left_match <=> right_match
226
221
  when 1
227
- :patch
222
+ if left_miss.zero?
223
+ :patch
224
+ else
225
+ :unpatch
226
+ end
228
227
  when -1
229
- :unpatch
228
+ if right_miss.zero?
229
+ :unpatch
230
+ else
231
+ :patch
232
+ end
230
233
  else
231
- 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."
232
236
  end
233
237
  end
234
238
  end
@@ -251,14 +255,14 @@ class << Diff::LCS::Internals
251
255
  # Binary search for the insertion point
252
256
  last_index ||= enum.size
253
257
  first_index = 0
254
- while (first_index <= last_index)
258
+ while first_index <= last_index
255
259
  i = (first_index + last_index) >> 1
256
260
 
257
261
  found = enum[i]
258
262
 
259
- if value == found
260
- return nil
261
- elsif value > found
263
+ return nil if value == found
264
+
265
+ if value > found
262
266
  first_index = i + 1
263
267
  else
264
268
  last_index = i - 1
@@ -268,7 +272,7 @@ class << Diff::LCS::Internals
268
272
  # The insertion point is in first_index; overwrite the next larger
269
273
  # value.
270
274
  enum[first_index] = value
271
- return first_index
275
+ first_index
272
276
  end
273
277
  private :replace_next_larger
274
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
@@ -148,16 +128,16 @@ class << Diff::LCS::Ldiff
148
128
 
149
129
  return 0 unless diffs
150
130
 
151
- if (@format == :report) and diffs
131
+ if @format == :report
152
132
  output << "Files #{file_old} and #{file_new} differ\n"
153
133
  return 1
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