diff-lcs 1.2.5 → 1.4.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 +6 -14
  2. data/.rspec +0 -1
  3. data/Code-of-Conduct.md +74 -0
  4. data/Contributing.md +118 -0
  5. data/History.md +319 -0
  6. data/{License.rdoc → License.md} +0 -0
  7. data/Manifest.txt +15 -8
  8. data/README.rdoc +18 -19
  9. data/Rakefile +57 -24
  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 +188 -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 +33 -36
  20. data/lib/diff/lcs/htmldiff.rb +17 -16
  21. data/lib/diff/lcs/hunk.rb +156 -74
  22. data/lib/diff/lcs/internals.rb +43 -40
  23. data/lib/diff/lcs/ldiff.rb +51 -75
  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 +54 -43
  37. data/spec/issues_spec.rb +147 -17
  38. data/spec/lcs_spec.rb +24 -22
  39. data/spec/ldiff_spec.rb +87 -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
File without changes
@@ -1,12 +1,8 @@
1
- .autotest
2
- .gemtest
3
- .hoerc
4
1
  .rspec
5
- .travis.yml
6
- Contributing.rdoc
7
- Gemfile
8
- History.rdoc
9
- License.rdoc
2
+ Code-of-Conduct.md
3
+ Contributing.md
4
+ History.md
5
+ License.md
10
6
  Manifest.txt
11
7
  README.rdoc
12
8
  Rakefile
@@ -18,6 +14,7 @@ docs/artistic.txt
18
14
  lib/diff-lcs.rb
19
15
  lib/diff/lcs.rb
20
16
  lib/diff/lcs/array.rb
17
+ lib/diff/lcs/backports.rb
21
18
  lib/diff/lcs/block.rb
22
19
  lib/diff/lcs/callbacks.rb
23
20
  lib/diff/lcs/change.rb
@@ -28,9 +25,19 @@ lib/diff/lcs/ldiff.rb
28
25
  lib/diff/lcs/string.rb
29
26
  spec/change_spec.rb
30
27
  spec/diff_spec.rb
28
+ spec/fixtures/aX
29
+ spec/fixtures/bXaX
30
+ spec/fixtures/ds1.csv
31
+ spec/fixtures/ds2.csv
32
+ spec/fixtures/ldiff/output.diff
33
+ spec/fixtures/ldiff/output.diff-c
34
+ spec/fixtures/ldiff/output.diff-e
35
+ spec/fixtures/ldiff/output.diff-f
36
+ spec/fixtures/ldiff/output.diff-u
31
37
  spec/hunk_spec.rb
32
38
  spec/issues_spec.rb
33
39
  spec/lcs_spec.rb
40
+ spec/ldiff_spec.rb
34
41
  spec/patch_spec.rb
35
42
  spec/sdiff_spec.rb
36
43
  spec/spec_helper.rb
@@ -1,9 +1,10 @@
1
1
  = Diff::LCS
2
2
 
3
- home :: http://diff-lcs.rubyforge.org/
3
+ home :: https://github.com/halostatue/diff-lcs
4
4
  code :: https://github.com/halostatue/diff-lcs
5
5
  bugs :: https://github.com/halostatue/diff-lcs/issues
6
6
  rdoc :: http://rubydoc.info/github/halostatue/diff-lcs
7
+ continuous integration :: {<img src="https://github.com/halostatue/diff-lcs/workflows/CI/badge.svg" />}[https://github.com/halostatue/diff-lcs/actions]
7
8
 
8
9
  == Description
9
10
 
@@ -11,14 +12,15 @@ Diff::LCS computes the difference between two Enumerable sequences using the
11
12
  McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities
12
13
  to create a simple HTML diff output format and a standard diff-like tool.
13
14
 
14
- This is release 1.2.4, fixing a bug introduced after diff-lcs 1.1.3 that did
15
- not properly prune common sequences at the beginning of a comparison set.
16
- Thanks to Paul Kunysch for fixing this issue.
15
+ This is release 1.4.3, providing a simple extension that allows for
16
+ Diff::LCS::Change objects to be treated implicitly as arrays and fixes a
17
+ number of formatting issues.
17
18
 
18
- Coincident with the release of diff-lcs 1.2.3, we reported an issue with
19
- Rubinius in 1.9 mode
20
- ({rubinius/rubinius#2268}[https://github.com/rubinius/rubinius/issues/2268]).
21
- We are happy to report that this issue has been resolved.
19
+ Ruby versions below 2.5 are soft-deprecated, which means that older versions
20
+ are no longer part of the CI test suite. If any changes have been introduced
21
+ that break those versions, bug reports and patches will be accepted, but it
22
+ will be up to the reporter to verify any fixes prior to release. The next
23
+ major release will completely break compatibility.
22
24
 
23
25
  == Synopsis
24
26
 
@@ -69,17 +71,14 @@ or Array will perform best.
69
71
  Diff::LCS is a port of Perl's Algorithm::Diff that uses the McIlroy-Hunt
70
72
  longest common subsequence (LCS) algorithm to compute intelligent differences
71
73
  between two sequenced enumerable containers. The implementation is based on
72
- Mario I. Wolczko's {Smalltalk version 1.2}[ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st]
74
+ Mario I. Wolczko's
75
+ {Smalltalk version 1.2}[ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st]
73
76
  (1993) and Ned Konz's Perl version
74
77
  {Algorithm::Diff 1.15}[http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15/].
78
+ Diff::LCS#sdiff and Diff::LCS#traverse_balanced were originally written for the
79
+ Perl version by Mike Schilli.
75
80
 
76
- This library is called Diff::LCS because of an early version of Algorithm::Diff
77
- which was restrictively licensed.
78
-
79
- == Continuous Integration Status
80
-
81
- {<img src="https://travis-ci.org/halostatue/diff-lcs.png" />}[https://travis-ci.org/halostatue/diff-lcs]
82
-
83
- :include: Contributing.rdoc
84
-
85
- :include: License.rdoc
81
+ The algorithm is described in <em>A Fast Algorithm for Computing Longest Common
82
+ Subsequences</em>, CACM, vol.20, no.5, pp.350-353, May 1977, with a few minor
83
+ improvements to improve the speed. A simplified description of the algorithm,
84
+ originally written for the Perl version, was written by Mark-Jason Dominus.
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rspec'
@@ -6,36 +6,69 @@ require 'hoe'
6
6
 
7
7
  Hoe.plugin :bundler
8
8
  Hoe.plugin :doofus
9
- Hoe.plugin :email
10
9
  Hoe.plugin :gemspec2
11
10
  Hoe.plugin :git
12
- Hoe.plugin :rubyforge
13
- Hoe.plugin :travis
14
11
 
15
- Hoe.spec 'diff-lcs' do
16
- developer('Austin Ziegler', 'austin@rubyforge.org')
12
+ if RUBY_VERSION < '1.9'
13
+ class Array #:nodoc:
14
+ def to_h
15
+ Hash[*flatten(1)]
16
+ end
17
+ end
17
18
 
18
- self.remote_rdoc_dir = '.'
19
- self.rsync_args << ' --exclude=statsvn/'
19
+ class Gem::Specification #:nodoc:
20
+ def metadata=(*); end
20
21
 
21
- self.history_file = 'History.rdoc'
22
+ def default_value(*); end
23
+ end
24
+
25
+ class Object #:nodoc:
26
+ def caller_locations(*)
27
+ []
28
+ end
29
+ end
30
+ end
31
+
32
+ _spec = Hoe.spec 'diff-lcs' do
33
+ developer('Austin Ziegler', 'halostatue@gmail.com')
34
+
35
+ require_ruby_version '>= 1.8'
36
+
37
+ self.history_file = 'History.md'
22
38
  self.readme_file = 'README.rdoc'
23
- self.extra_rdoc_files = FileList["*.rdoc"].to_a
24
-
25
- %w(MIT Perl\ Artistic\ v2 GNU\ GPL\ v2).each { |l| self.license l }
26
-
27
- self.extra_dev_deps << ['hoe-bundler', '~> 1.2']
28
- self.extra_dev_deps << ['hoe-doofus', '~> 1.0']
29
- self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
30
- self.extra_dev_deps << ['hoe-git', '~> 1.5']
31
- self.extra_dev_deps << ['hoe-rubygems', '~> 1.0']
32
- self.extra_dev_deps << ['hoe-travis', '~> 1.2']
33
- self.extra_dev_deps << ['rake', '~> 10.0']
34
- self.extra_dev_deps << ['rspec', '~> 2.0']
39
+ self.licenses = ['MIT', 'Artistic-2.0', 'GPL-2.0+']
40
+
41
+ extra_dev_deps << ['hoe-doofus', '~> 1.0']
42
+ extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
43
+ extra_dev_deps << ['hoe-git', '~> 1.6']
44
+ extra_dev_deps << ['hoe-rubygems', '~> 1.0']
45
+ extra_dev_deps << ['rspec', '>= 2.0', '< 4']
46
+ extra_dev_deps << ['rake', '>= 10.0', '< 14']
47
+ extra_dev_deps << ['rdoc', '>= 0']
35
48
  end
36
49
 
37
- unless Rake::Task.task_defined? :test
38
- task :test => :spec
50
+ if RUBY_VERSION >= '2.0' && RUBY_ENGINE == 'ruby'
51
+ namespace :spec do
52
+ desc "Runs test coverage. Only works Ruby 2.0+ and assumes 'simplecov' is installed."
53
+ task :coverage do
54
+ ENV['COVERAGE'] = 'yes'
55
+ Rake::Task['spec'].execute
56
+ end
57
+ end
39
58
  end
40
59
 
41
- # vim: syntax=ruby
60
+ task :ruby18 do
61
+ puts <<-MESSAGE
62
+ You are starting a barebones Ruby 1.8 docker environment. You will need to
63
+ do the following:
64
+
65
+ - mv Gemfile.lock{,.v2}
66
+ - gem install bundler --version 1.17.2 --no-ri --no-rdoc
67
+ - ruby -S bundle
68
+ - rake
69
+
70
+ Don't forget to restore your Gemfile.lock after testing.
71
+
72
+ MESSAGE
73
+ sh "docker run -it --rm -v #{Dir.pwd}:/root/diff-lcs bellbind/docker-ruby18-rails2 bash -l"
74
+ end
@@ -1 +1,3 @@
1
- Autotest.add_discovery { "rspec2" }
1
+ # frozen_string_literal: true
2
+
3
+ Autotest.add_discovery { 'rspec2' }
@@ -1,4 +1,5 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/htmldiff'
@@ -10,8 +11,8 @@ rescue LoadError
10
11
  end
11
12
 
12
13
  if ARGV.size < 2 or ARGV.size > 3
13
- $stderr.puts "usage: #{File.basename($0)} old new [output.html]"
14
- $stderr.puts " #{File.basename($0)} old new > output.html"
14
+ warn "usage: #{File.basename($0)} old new [output.html]"
15
+ warn " #{File.basename($0)} old new > output.html"
15
16
  exit 127
16
17
  end
17
18
 
@@ -23,10 +24,12 @@ options = { :title => "diff #{ARGV[0]} #{ARGV[1]}" }
23
24
  htmldiff = Diff::LCS::HTMLDiff.new(left, right, options)
24
25
 
25
26
  if ARGV[2]
26
- File.open(ARGV[2], "w") do |f|
27
+ File.open(ARGV[2], 'w') do |f|
27
28
  htmldiff.options[:output] = f
28
29
  htmldiff.run
29
30
  end
30
31
  else
31
32
  htmldiff.run
32
33
  end
34
+
35
+ # vim: ft=ruby
data/bin/ldiff CHANGED
@@ -1,6 +1,9 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/ldiff'
5
6
 
6
7
  exit Diff::LCS::Ldiff.run(ARGV)
8
+
9
+ # vim: ft=ruby
@@ -1,3 +1,3 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'diff/lcs'
@@ -1,76 +1,24 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
- module Diff; end unless defined? Diff
4
- # = Diff::LCS 1.2.5
5
- #
6
- # Computes "intelligent" differences between two sequenced Enumerables. This
7
- # is an implementation of the McIlroy-Hunt "diff" algorithm for Enumerable
8
- # objects that include Diffable.
9
- #
10
- # Based on Mario I. Wolczko's Smalltalk version (1.2, 1993) and Ned Konz's
11
- # Perl version (Algorithm::Diff 1.15).
12
- #
13
- # == Synopsis
14
- # require 'diff/lcs'
15
- #
16
- # seq1 = %w(a b c e h j l m n p)
17
- # seq2 = %w(b c d e f j k l m r s t)
18
- #
19
- # lcs = Diff::LCS.lcs(seq1, seq2)
20
- # diffs = Diff::LCS.diff(seq1, seq2)
21
- # sdiff = Diff::LCS.sdiff(seq1, seq2)
22
- # seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj)
23
- # bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj)
24
- # seq2 == Diff::LCS.patch(seq1, diffs)
25
- # seq2 == Diff::LCS.patch!(seq1, diffs)
26
- # seq1 == Diff::LCS.unpatch(seq2, diffs)
27
- # seq1 == Diff::LCS.unpatch!(seq2, diffs)
28
- # seq2 == Diff::LCS.patch(seq1, sdiff)
29
- # seq2 == Diff::LCS.patch!(seq1, sdiff)
30
- # seq1 == Diff::LCS.unpatch(seq2, sdiff)
31
- # seq1 == Diff::LCS.unpatch!(seq2, sdiff)
32
- #
33
- # Alternatively, objects can be extended with Diff::LCS:
34
- #
35
- # seq1.extend(Diff::LCS)
36
- # lcs = seq1.lcs(seq2)
37
- # diffs = seq1.diff(seq2)
38
- # sdiff = seq1.sdiff(seq2)
39
- # seq = seq1.traverse_sequences(seq2, callback_obj)
40
- # bal = seq1.traverse_balanced(seq2, callback_obj)
41
- # seq2 == seq1.patch(diffs)
42
- # seq2 == seq1.patch!(diffs)
43
- # seq1 == seq2.unpatch(diffs)
44
- # seq1 == seq2.unpatch!(diffs)
45
- # seq2 == seq1.patch(sdiff)
46
- # seq2 == seq1.patch!(sdiff)
47
- # seq1 == seq2.unpatch(sdiff)
48
- # seq1 == seq2.unpatch!(sdiff)
49
- #
50
- # Default extensions are provided for Array and String objects through the
51
- # use of 'diff/lcs/array' and 'diff/lcs/string'.
52
- #
53
- # == Introduction (by Mark-Jason Dominus)
54
- #
55
- # <em>The following text is from the Perl documentation. The only changes
56
- # have been to make the text appear better in Rdoc</em>.
3
+ module Diff; end unless defined? Diff # rubocop:disable Style/Documentation
4
+
5
+ # == How Diff Works (by Mark-Jason Dominus)
57
6
  #
58
- # I once read an article written by the authors of +diff+; they said that
59
- # they hard worked very hard on the algorithm until they found the right
60
- # one.
7
+ # I once read an article written by the authors of +diff+; they said that they
8
+ # hard worked very hard on the algorithm until they found the right one.
61
9
  #
62
- # I think what they ended up using (and I hope someone will correct me,
63
- # because I am not very confident about this) was the `longest common
64
- # subsequence' method. In the LCS problem, you have two sequences of items:
10
+ # I think what they ended up using (and I hope someone will correct me, because
11
+ # I am not very confident about this) was the `longest common subsequence'
12
+ # method. In the LCS problem, you have two sequences of items:
65
13
  #
66
14
  # a b c d f g h j q z
67
15
  # a b c d e f g i j k r x y z
68
16
  #
69
17
  # and you want to find the longest sequence of items that is present in both
70
18
  # original sequences in the same order. That is, you want to find a new
71
- # sequence *S* which can be obtained from the first sequence by deleting
72
- # some items, and from the second sequence by deleting other items. You also
73
- # want *S* to be as long as possible. In this case *S* is:
19
+ # sequence *S* which can be obtained from the first sequence by deleting some
20
+ # items, and from the second sequence by deleting other items. You also want
21
+ # *S* to be as long as possible. In this case *S* is:
74
22
  #
75
23
  # a b c d f g j z
76
24
  #
@@ -82,9 +30,9 @@ module Diff; end unless defined? Diff
82
30
  # This module solves the LCS problem. It also includes a canned function to
83
31
  # generate +diff+-like output.
84
32
  #
85
- # It might seem from the example above that the LCS of two sequences is
86
- # always pretty obvious, but that's not always the case, especially when the
87
- # two sequences have many repeated elements. For example, consider
33
+ # It might seem from the example above that the LCS of two sequences is always
34
+ # pretty obvious, but that's not always the case, especially when the two
35
+ # sequences have many repeated elements. For example, consider
88
36
  #
89
37
  # a x b y c z p d q
90
38
  # a b c a x b y c z
@@ -95,57 +43,35 @@ module Diff; end unless defined? Diff
95
43
  # a x b y c z p d q
96
44
  # a b c a b y c z
97
45
  #
98
- # This finds the common subsequence +a b c z+. But actually, the LCS is +a x
99
- # b y c z+:
46
+ # This finds the common subsequence +a b c z+. But actually, the LCS is +a x b
47
+ # y c z+:
100
48
  #
101
49
  # a x b y c z p d q
102
50
  # a b c a x b y c z
103
- #
104
- # == Author
105
- # This version is by Austin Ziegler <austin@rubyforge.org>.
106
- #
107
- # It is based on the Perl Algorithm::Diff (1.15) by Ned Konz , copyright
108
- # &copy; 2000&ndash;2002 and the Smalltalk diff version by Mario I.
109
- # Wolczko, copyright &copy; 1993. Documentation includes work by
110
- # Mark-Jason Dominus.
111
- #
112
- # == Licence
113
- # Copyright &copy; 2004&ndash;2013 Austin Ziegler
114
- # This program is free software; you can redistribute it and/or modify it
115
- # under the same terms as Ruby, or alternatively under the Perl Artistic
116
- # licence.
117
- #
118
- # == Credits
119
- # Much of the documentation is taken directly from the Perl Algorithm::Diff
120
- # implementation and was written originally by Mark-Jason Dominus and later
121
- # by Ned Konz. The basic Ruby implementation was re-ported from the
122
- # Smalltalk implementation, available at
123
- # ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st
124
- #
125
- # #sdiff and #traverse_balanced were written for the Perl version by Mike
126
- # Schilli <m@perlmeister.com>.
127
- #
128
- # "The algorithm is described in <em>A Fast Algorithm for Computing Longest
129
- # Common Subsequences</em>, CACM, vol.20, no.5, pp.350-353, May
130
- # 1977, with a few minor improvements to improve the speed."
131
51
  module Diff::LCS
132
- VERSION = '1.2.5'
52
+ VERSION = '1.4.4'
133
53
  end
134
54
 
135
55
  require 'diff/lcs/callbacks'
136
56
  require 'diff/lcs/internals'
137
57
 
138
- module Diff::LCS
58
+ module Diff::LCS # rubocop:disable Style/Documentation
139
59
  # Returns an Array containing the longest common subsequence(s) between
140
- # +self+ and +other+. See Diff::LCS#LCS.
60
+ # +self+ and +other+. See Diff::LCS#lcs.
141
61
  #
142
62
  # lcs = seq1.lcs(seq2)
63
+ #
64
+ # A note when using objects: Diff::LCS only works properly when each object
65
+ # can be used as a key in a Hash, which typically means that the objects must
66
+ # implement Object#eql? in a way that two identical values compare
67
+ # identically for key purposes. That is:
68
+ #
69
+ # O.new('a').eql?(O.new('a')) == true
143
70
  def lcs(other, &block) #:yields self[i] if there are matched subsequences:
144
71
  Diff::LCS.lcs(self, other, &block)
145
72
  end
146
73
 
147
- # Returns the difference set between +self+ and +other+. See
148
- # Diff::LCS#diff.
74
+ # Returns the difference set between +self+ and +other+. See Diff::LCS#diff.
149
75
  def diff(other, callbacks = nil, &block)
150
76
  Diff::LCS.diff(self, other, callbacks, &block)
151
77
  end
@@ -159,29 +85,27 @@ module Diff::LCS
159
85
  # Traverses the discovered longest common subsequences between +self+ and
160
86
  # +other+. See Diff::LCS#traverse_sequences.
161
87
  def traverse_sequences(other, callbacks = nil, &block)
162
- traverse_sequences(self, other, callbacks ||
163
- Diff::LCS.YieldingCallbacks, &block)
88
+ traverse_sequences(self, other, callbacks || Diff::LCS::SequenceCallbacks, &block)
164
89
  end
165
90
 
166
91
  # Traverses the discovered longest common subsequences between +self+ and
167
92
  # +other+ using the alternate, balanced algorithm. See
168
93
  # Diff::LCS#traverse_balanced.
169
94
  def traverse_balanced(other, callbacks = nil, &block)
170
- traverse_balanced(self, other, callbacks ||
171
- Diff::LCS.YieldingCallbacks, &block)
95
+ traverse_balanced(self, other, callbacks || Diff::LCS::BalancedCallbacks, &block)
172
96
  end
173
97
 
174
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
175
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
176
- # Attempts to autodiscover the direction of the patch.
98
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
99
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Attempts
100
+ # to autodiscover the direction of the patch.
177
101
  def patch(patchset)
178
102
  Diff::LCS.patch(self, patchset)
179
103
  end
180
- alias_method :unpatch, :patch
104
+ alias unpatch patch
181
105
 
182
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
183
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
184
- # Does no patch direction autodiscovery.
106
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
107
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Does no
108
+ # patch direction autodiscovery.
185
109
  def patch!(patchset)
186
110
  Diff::LCS.patch!(self, patchset)
187
111
  end
@@ -194,8 +118,8 @@ module Diff::LCS
194
118
  end
195
119
 
196
120
  # Attempts to patch +self+ with the provided +patchset+, using #patch!. If
197
- # the sequence this is used on supports #replace, the value of +self+ will
198
- # be replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
121
+ # the sequence this is used on supports #replace, the value of +self+ will be
122
+ # replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
199
123
  def patch_me(patchset)
200
124
  if respond_to? :replace
201
125
  replace(patch!(patchset))
@@ -204,10 +128,9 @@ module Diff::LCS
204
128
  end
205
129
  end
206
130
 
207
- # Attempts to unpatch +self+ with the provided +patchset+, using
208
- # #unpatch!. If the sequence this is used on supports #replace, the value
209
- # of +self+ will be replaced. See Diff::LCS#unpatch. Does no patch direction
210
- # autodiscovery.
131
+ # Attempts to unpatch +self+ with the provided +patchset+, using #unpatch!.
132
+ # If the sequence this is used on supports #replace, the value of +self+ will
133
+ # be replaced. See Diff::LCS#unpatch. Does no patch direction autodiscovery.
211
134
  def unpatch_me(patchset)
212
135
  if respond_to? :replace
213
136
  replace(unpatch!(patchset))
@@ -222,29 +145,28 @@ class << Diff::LCS
222
145
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
223
146
  ret = []
224
147
  string = seq1.kind_of? String
225
- matches.each_with_index do |e, i|
226
- unless matches[i].nil?
227
- v = string ? seq1[i, 1] : seq1[i]
228
- v = block[v] if block
229
- ret << v
230
- end
148
+ matches.each_with_index do |_e, i|
149
+ next if matches[i].nil?
150
+
151
+ v = string ? seq1[i, 1] : seq1[i]
152
+ v = block[v] if block
153
+ ret << v
231
154
  end
232
155
  ret
233
156
  end
234
- alias_method :LCS, :lcs
157
+ alias LCS lcs
235
158
 
236
159
  # #diff computes the smallest set of additions and deletions necessary to
237
- # turn the first sequence into the second, and returns a description of
238
- # these changes.
160
+ # turn the first sequence into the second, and returns a description of these
161
+ # changes.
239
162
  #
240
163
  # See Diff::LCS::DiffCallbacks for the default behaviour. An alternate
241
164
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
242
165
  # Class argument is provided for +callbacks+, #diff will attempt to
243
- # initialise it. If the +callbacks+ object (possibly initialised) responds
244
- # to #finish, it will be called.
166
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
167
+ # #finish, it will be called.
245
168
  def diff(seq1, seq2, callbacks = nil, &block) # :yields diff changes:
246
- diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks,
247
- &block)
169
+ diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks, &block)
248
170
  end
249
171
 
250
172
  # #sdiff computes all necessary components to show two sequences and their
@@ -259,18 +181,31 @@ class << Diff::LCS
259
181
  # See Diff::LCS::SDiffCallbacks for the default behaviour. An alternate
260
182
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
261
183
  # Class argument is provided for +callbacks+, #diff will attempt to
262
- # initialise it. If the +callbacks+ object (possibly initialised) responds
263
- # to #finish, it will be called.
184
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
185
+ # #finish, it will be called.
186
+ #
187
+ # Each element of a returned array is a Diff::LCS::ContextChange object,
188
+ # which can be implicitly converted to an array.
189
+ #
190
+ # Diff::LCS.sdiff(a, b).each do |action, (old_pos, old_element), (new_pos, new_element)|
191
+ # case action
192
+ # when '!'
193
+ # # replace
194
+ # when '-'
195
+ # # delete
196
+ # when '+'
197
+ # # insert
198
+ # end
199
+ # end
264
200
  def sdiff(seq1, seq2, callbacks = nil, &block) #:yields diff changes:
265
- diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks,
266
- &block)
201
+ diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks, &block)
267
202
  end
268
203
 
269
- # #traverse_sequences is the most general facility provided by this
270
- # module; #diff and #lcs are implemented as calls to it.
204
+ # #traverse_sequences is the most general facility provided by this module;
205
+ # #diff and #lcs are implemented as calls to it.
271
206
  #
272
- # The arguments to #traverse_sequences are the two sequences to traverse,
273
- # and a callback object, like this:
207
+ # The arguments to #traverse_sequences are the two sequences to traverse, and
208
+ # a callback object, like this:
274
209
  #
275
210
  # traverse_sequences(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
276
211
  #
@@ -298,56 +233,55 @@ class << Diff::LCS
298
233
  # ^
299
234
  # b---+
300
235
  #
301
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
302
- # +A+ and +B+, the arrows will initially point to the first elements of
303
- # their respective sequences. #traverse_sequences will advance the arrows
304
- # through the sequences one element at a time, calling a method on the
305
- # user-specified callback object before each advance. It will advance the
306
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
307
- # <tt>B[j]</tt> which are both equal and part of the longest common
308
- # subsequence, there will be some moment during the execution of
309
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
310
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
311
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
312
- # advance both arrows.
313
- #
314
- # Otherwise, one of the arrows is pointing to an element of its sequence
315
- # that is not part of the longest common subsequence. #traverse_sequences
316
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
317
- # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If
318
- # both arrows point to elements that are not part of the longest common
319
- # subsequence, then #traverse_sequences will advance one of them and call
320
- # the appropriate callback, but it is not specified which it will call.
321
- #
322
- # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
323
- # and <tt>callbacks#discard_b</tt> are invoked with an event comprising
324
- # the action ("=", "+", or "-", respectively), the indicies +i+ and +j+,
325
- # and the elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are
326
- # discarded by #traverse_sequences.
236
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
237
+ # and +B+, the arrows will initially point to the first elements of their
238
+ # respective sequences. #traverse_sequences will advance the arrows through
239
+ # the sequences one element at a time, calling a method on the user-specified
240
+ # callback object before each advance. It will advance the arrows in such a
241
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
242
+ # both equal and part of the longest common subsequence, there will be some
243
+ # moment during the execution of #traverse_sequences when arrow +a+ is
244
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
245
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
246
+ # then it will advance both arrows.
247
+ #
248
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
249
+ # is not part of the longest common subsequence. #traverse_sequences will
250
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
251
+ # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If both
252
+ # arrows point to elements that are not part of the longest common
253
+ # subsequence, then #traverse_sequences will advance one of them and call the
254
+ # appropriate callback, but it is not specified which it will call.
255
+ #
256
+ # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>, and
257
+ # <tt>callbacks#discard_b</tt> are invoked with an event comprising the
258
+ # action ("=", "+", or "-", respectively), the indicies +i+ and +j+, and the
259
+ # elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
260
+ # #traverse_sequences.
327
261
  #
328
262
  # === End of Sequences
329
263
  #
330
264
  # If arrow +a+ reaches the end of its sequence before arrow +b+ does,
331
- # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with
332
- # the last index and element of +A+ (<tt>A[-1]</tt>) and the current index
333
- # and element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt>
334
- # does not exist, then <tt>callbacks#discard_b</tt> will be called on each
335
- # element of +B+ until the end of the sequence is reached (the call will
336
- # be done with <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
265
+ # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with the
266
+ # last index and element of +A+ (<tt>A[-1]</tt>) and the current index and
267
+ # element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt> does not
268
+ # exist, then <tt>callbacks#discard_b</tt> will be called on each element of
269
+ # +B+ until the end of the sequence is reached (the call will be done with
270
+ # <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
337
271
  #
338
272
  # If +b+ reaches the end of +B+ before +a+ reaches the end of +A+,
339
273
  # <tt>callbacks#finished_b</tt> will be called with the current index and
340
274
  # element of +A+ (<tt>A[i]</tt>) and the last index and element of +B+
341
- # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist
342
- # on the callback object, then <tt>callbacks#discard_a</tt> will be called
343
- # on each element of +A+ until the end of the sequence is reached
344
- # (<tt>A[i]</tt> and <tt>B[-1]</tt>).
275
+ # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist on
276
+ # the callback object, then <tt>callbacks#discard_a</tt> will be called on
277
+ # each element of +A+ until the end of the sequence is reached (<tt>A[i]</tt>
278
+ # and <tt>B[-1]</tt>).
345
279
  #
346
280
  # There is a chance that one additional <tt>callbacks#discard_a</tt> or
347
- # <tt>callbacks#discard_b</tt> will be called after the end of the
348
- # sequence is reached, if +a+ has not yet reached the end of +A+ or +b+
349
- # has not yet reached the end of +B+.
350
- def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &block) #:yields change events:
281
+ # <tt>callbacks#discard_b</tt> will be called after the end of the sequence
282
+ # is reached, if +a+ has not yet reached the end of +A+ or +b+ has not yet
283
+ # reached the end of +B+.
284
+ def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks) #:yields change events:
351
285
  callbacks ||= Diff::LCS::SequenceCallbacks
352
286
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
353
287
 
@@ -373,6 +307,7 @@ class << Diff::LCS
373
307
  else
374
308
  loop do
375
309
  break unless bj < b_line
310
+
376
311
  bx = string ? seq2[bj, 1] : seq2[bj]
377
312
  event = Diff::LCS::ContextChange.new('+', i, ax, bj, bx)
378
313
  event = yield event if block_given?
@@ -389,12 +324,12 @@ class << Diff::LCS
389
324
  end
390
325
  ai += 1
391
326
 
392
- # The last entry (if any) processed was a match. +ai+ and +bj+ point
393
- # just past the last matching lines in their sequences.
327
+ # The last entry (if any) processed was a match. +ai+ and +bj+ point just
328
+ # past the last matching lines in their sequences.
394
329
  while (ai < a_size) or (bj < b_size)
395
330
  # last A?
396
331
  if ai == a_size and bj < b_size
397
- if callbacks.respond_to?(:finished_a) and not run_finished_a
332
+ if callbacks.respond_to?(:finished_a) and !run_finished_a
398
333
  ax = string ? seq1[-1, 1] : seq1[-1]
399
334
  bx = string ? seq2[bj, 1] : seq2[bj]
400
335
  event = Diff::LCS::ContextChange.new('>', (a_size - 1), ax, bj, bx)
@@ -416,7 +351,7 @@ class << Diff::LCS
416
351
 
417
352
  # last B?
418
353
  if bj == b_size and ai < a_size
419
- if callbacks.respond_to?(:finished_b) and not run_finished_b
354
+ if callbacks.respond_to?(:finished_b) and !run_finished_b
420
355
  ax = string ? seq1[ai, 1] : seq1[ai]
421
356
  bx = string ? seq2[-1, 1] : seq2[-1]
422
357
  event = Diff::LCS::ContextChange.new('<', ai, ax, (b_size - 1), bx)
@@ -445,25 +380,25 @@ class << Diff::LCS
445
380
  ai += 1
446
381
  end
447
382
 
448
- if bj < b_size
449
- ax = string ? seq1[ai, 1] : seq1[ai]
450
- bx = string ? seq2[bj, 1] : seq2[bj]
451
- event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
452
- event = yield event if block_given?
453
- callbacks.discard_b(event)
454
- bj += 1
455
- end
383
+ next unless bj < b_size
384
+
385
+ ax = string ? seq1[ai, 1] : seq1[ai]
386
+ bx = string ? seq2[bj, 1] : seq2[bj]
387
+ event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
388
+ event = yield event if block_given?
389
+ callbacks.discard_b(event)
390
+ bj += 1
456
391
  end
457
392
  end
458
393
 
459
394
  # #traverse_balanced is an alternative to #traverse_sequences. It uses a
460
- # different algorithm to iterate through the entries in the computed
461
- # longest common subsequence. Instead of viewing the changes as insertions
462
- # or deletions from one of the sequences, #traverse_balanced will report
395
+ # different algorithm to iterate through the entries in the computed longest
396
+ # common subsequence. Instead of viewing the changes as insertions or
397
+ # deletions from one of the sequences, #traverse_balanced will report
463
398
  # <em>changes</em> between the sequences.
464
399
  #
465
- # The arguments to #traverse_balanced are the two sequences to traverse
466
- # and a callback object, like this:
400
+ # The arguments to #traverse_balanced are the two sequences to traverse and a
401
+ # callback object, like this:
467
402
  #
468
403
  # traverse_balanced(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
469
404
  #
@@ -499,24 +434,23 @@ class << Diff::LCS
499
434
  #
500
435
  # === Matches
501
436
  #
502
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
503
- # +A+ and +B+, the arrows will initially point to the first elements of
504
- # their respective sequences. #traverse_sequences will advance the arrows
505
- # through the sequences one element at a time, calling a method on the
506
- # user-specified callback object before each advance. It will advance the
507
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
508
- # <tt>B[j]</tt> which are both equal and part of the longest common
509
- # subsequence, there will be some moment during the execution of
510
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
511
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
512
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
513
- # advance both arrows.
437
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
438
+ # and +B+, the arrows will initially point to the first elements of their
439
+ # respective sequences. #traverse_sequences will advance the arrows through
440
+ # the sequences one element at a time, calling a method on the user-specified
441
+ # callback object before each advance. It will advance the arrows in such a
442
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
443
+ # both equal and part of the longest common subsequence, there will be some
444
+ # moment during the execution of #traverse_sequences when arrow +a+ is
445
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
446
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
447
+ # then it will advance both arrows.
514
448
  #
515
449
  # === Discards
516
450
  #
517
- # Otherwise, one of the arrows is pointing to an element of its sequence
518
- # that is not part of the longest common subsequence. #traverse_sequences
519
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
451
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
452
+ # is not part of the longest common subsequence. #traverse_sequences will
453
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
520
454
  # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced.
521
455
  #
522
456
  # === Changes
@@ -530,14 +464,14 @@ class << Diff::LCS
530
464
  #
531
465
  # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
532
466
  # <tt>callbacks#discard_b</tt>, and <tt>callbacks#change</tt> are invoked
533
- # with an event comprising the action ("=", "+", "-", or "!",
534
- # respectively), the indicies +i+ and +j+, and the elements
535
- # <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
536
- # #traverse_balanced.
467
+ # with an event comprising the action ("=", "+", "-", or "!", respectively),
468
+ # the indicies +i+ and +j+, and the elements <tt>A[i]</tt> and <tt>B[j]</tt>.
469
+ # Return values are discarded by #traverse_balanced.
537
470
  #
538
471
  # === Context
539
- # Note that +i+ and +j+ may not be the same index position, even if +a+
540
- # and +b+ are considered to be pointing to matching or changed elements.
472
+ #
473
+ # Note that +i+ and +j+ may not be the same index position, even if +a+ and
474
+ # +b+ are considered to be pointing to matching or changed elements.
541
475
  def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks)
542
476
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
543
477
  a_size = seq1.size
@@ -555,6 +489,7 @@ class << Diff::LCS
555
489
  end
556
490
 
557
491
  break if ma >= matches.size # end of matches?
492
+
558
493
  mb = matches[ma]
559
494
 
560
495
  # Change(seq2)
@@ -569,7 +504,6 @@ class << Diff::LCS
569
504
  event = yield event if block_given?
570
505
  callbacks.change(event)
571
506
  ai += 1
572
- bj += 1
573
507
  else
574
508
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
575
509
  event = yield event if block_given?
@@ -579,8 +513,9 @@ class << Diff::LCS
579
513
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
580
514
  event = yield event if block_given?
581
515
  callbacks.discard_b(event)
582
- bj += 1
583
516
  end
517
+
518
+ bj += 1
584
519
  when [true, false]
585
520
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
586
521
  event = yield event if block_given?
@@ -615,7 +550,6 @@ class << Diff::LCS
615
550
  event = yield event if block_given?
616
551
  callbacks.change(event)
617
552
  ai += 1
618
- bj += 1
619
553
  else
620
554
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
621
555
  event = yield event if block_given?
@@ -625,8 +559,9 @@ class << Diff::LCS
625
559
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
626
560
  event = yield event if block_given?
627
561
  callbacks.discard_b(event)
628
- bj += 1
629
562
  end
563
+
564
+ bj += 1
630
565
  when [true, false]
631
566
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
632
567
  event = yield event if block_given?
@@ -642,9 +577,9 @@ class << Diff::LCS
642
577
  end
643
578
 
644
579
  PATCH_MAP = { #:nodoc:
645
- :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' },
646
- :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }
647
- }
580
+ :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' }.freeze,
581
+ :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }.freeze
582
+ }.freeze
648
583
 
649
584
  # Applies a +patchset+ to the sequence +src+ according to the +direction+
650
585
  # (<tt>:patch</tt> or <tt>:unpatch</tt>), producing a new sequence.
@@ -657,23 +592,23 @@ class << Diff::LCS
657
592
  #
658
593
  # patch(s1, diff(s1, s2)) -> s2
659
594
  #
660
- # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if
661
- # the following expression is true:
595
+ # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if the
596
+ # following expression is true:
662
597
  #
663
598
  # patch(s2, diff(s1, s2)) -> s1
664
599
  #
665
- # If the +patchset+ contains no changes, the +src+ value will be returned
666
- # as either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as
667
- # having no changes if the following predicate returns true:
600
+ # If the +patchset+ contains no changes, the +src+ value will be returned as
601
+ # either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as having no
602
+ # changes if the following predicate returns true:
668
603
  #
669
604
  # patchset.empty? or
670
- # patchset.flatten.all? { |change| change.unchanged? }
605
+ # patchset.flatten(1).all? { |change| change.unchanged? }
671
606
  #
672
607
  # === Patchsets
673
608
  #
674
- # A +patchset+ is always an enumerable sequence of changes, hunks of
675
- # changes, or a mix of the two. A hunk of changes is an enumerable
676
- # sequence of changes:
609
+ # A +patchset+ is always an enumerable sequence of changes, hunks of changes,
610
+ # or a mix of the two. A hunk of changes is an enumerable sequence of
611
+ # changes:
677
612
  #
678
613
  # [ # patchset
679
614
  # # change
@@ -682,18 +617,15 @@ class << Diff::LCS
682
617
  # ]
683
618
  # ]
684
619
  #
685
- # The +patch+ method accepts <tt>patchset</tt>s that are enumerable
686
- # sequences containing either Diff::LCS::Change objects (or a subclass) or
687
- # the array representations of those objects. Prior to application, array
620
+ # The +patch+ method accepts <tt>patchset</tt>s that are enumerable sequences
621
+ # containing either Diff::LCS::Change objects (or a subclass) or the array
622
+ # representations of those objects. Prior to application, array
688
623
  # representations of Diff::LCS::Change objects will be reified.
689
624
  def patch(src, patchset, direction = nil)
690
625
  # Normalize the patchset.
691
626
  has_changes, patchset = Diff::LCS::Internals.analyze_patchset(patchset)
692
627
 
693
- if not has_changes
694
- return src.dup if src.respond_to? :dup
695
- return src
696
- end
628
+ return src.respond_to?(:dup) ? src.dup : src unless has_changes
697
629
 
698
630
  string = src.kind_of?(String)
699
631
  # Start with a new empty type of the source's class
@@ -705,7 +637,7 @@ class << Diff::LCS
705
637
 
706
638
  patch_map = PATCH_MAP[direction]
707
639
 
708
- patchset.flatten.each do |change|
640
+ patchset.each do |change|
709
641
  # Both Change and ContextChange support #action
710
642
  action = patch_map[change.action]
711
643
 
@@ -737,8 +669,8 @@ class << Diff::LCS
737
669
  bj += 1
738
670
  end
739
671
 
740
- res << el
741
- bj += 1
672
+ res << el
673
+ bj += 1
742
674
  when '='
743
675
  # This only appears in sdiff output with the SDiff callback.
744
676
  # Therefore, we only need to worry about dealing with a single
@@ -754,10 +686,10 @@ class << Diff::LCS
754
686
  bj += 1
755
687
  end
756
688
 
757
- bj += 1
758
- ai += 1
689
+ bj += 1
690
+ ai += 1
759
691
 
760
- res << el
692
+ res << el
761
693
  end
762
694
  when Diff::LCS::Change
763
695
  case action
@@ -767,7 +699,7 @@ class << Diff::LCS
767
699
  ai += 1
768
700
  bj += 1
769
701
  end
770
- ai += 1
702
+ ai += 1
771
703
  when '+'
772
704
  while bj < change.position
773
705
  res << (string ? src[ai, 1] : src[ai])
@@ -775,9 +707,9 @@ class << Diff::LCS
775
707
  bj += 1
776
708
  end
777
709
 
778
- bj += 1
710
+ bj += 1
779
711
 
780
- res << change.element
712
+ res << change.element
781
713
  end
782
714
  end
783
715
  end
@@ -791,15 +723,17 @@ class << Diff::LCS
791
723
  res
792
724
  end
793
725
 
794
- # Given a set of patchset, convert the current version to the prior
795
- # version. Does no auto-discovery.
726
+ # Given a set of patchset, convert the current version to the prior version.
727
+ # Does no auto-discovery.
796
728
  def unpatch!(src, patchset)
797
729
  patch(src, patchset, :unpatch)
798
730
  end
799
731
 
800
- # Given a set of patchset, convert the current version to the next
801
- # version. Does no auto-discovery.
732
+ # Given a set of patchset, convert the current version to the next version.
733
+ # Does no auto-discovery.
802
734
  def patch!(src, patchset)
803
735
  patch(src, patchset, :patch)
804
736
  end
805
737
  end
738
+
739
+ require 'diff/lcs/backports'