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.
- checksums.yaml +6 -14
- data/.rspec +0 -1
- data/Code-of-Conduct.md +74 -0
- data/Contributing.md +118 -0
- data/History.md +319 -0
- data/{License.rdoc → License.md} +0 -0
- data/Manifest.txt +15 -8
- data/README.rdoc +18 -19
- data/Rakefile +57 -24
- data/autotest/discover.rb +3 -1
- data/bin/htmldiff +7 -4
- data/bin/ldiff +4 -1
- data/lib/diff-lcs.rb +1 -1
- data/lib/diff/lcs.rb +188 -254
- data/lib/diff/lcs/array.rb +1 -1
- data/lib/diff/lcs/backports.rb +9 -0
- data/lib/diff/lcs/block.rb +1 -1
- data/lib/diff/lcs/callbacks.rb +15 -12
- data/lib/diff/lcs/change.rb +33 -36
- data/lib/diff/lcs/htmldiff.rb +17 -16
- data/lib/diff/lcs/hunk.rb +156 -74
- data/lib/diff/lcs/internals.rb +43 -40
- data/lib/diff/lcs/ldiff.rb +51 -75
- data/lib/diff/lcs/string.rb +1 -1
- data/spec/change_spec.rb +31 -7
- data/spec/diff_spec.rb +24 -20
- data/spec/fixtures/aX +1 -0
- data/spec/fixtures/bXaX +1 -0
- data/spec/fixtures/ds1.csv +50 -0
- data/spec/fixtures/ds2.csv +51 -0
- data/spec/fixtures/ldiff/output.diff +4 -0
- data/spec/fixtures/ldiff/output.diff-c +7 -0
- data/spec/fixtures/ldiff/output.diff-e +3 -0
- data/spec/fixtures/ldiff/output.diff-f +3 -0
- data/spec/fixtures/ldiff/output.diff-u +5 -0
- data/spec/hunk_spec.rb +54 -43
- data/spec/issues_spec.rb +147 -17
- data/spec/lcs_spec.rb +24 -22
- data/spec/ldiff_spec.rb +87 -0
- data/spec/patch_spec.rb +182 -180
- data/spec/sdiff_spec.rb +91 -91
- data/spec/spec_helper.rb +143 -58
- data/spec/traverse_balanced_spec.rb +177 -177
- data/spec/traverse_sequences_spec.rb +63 -63
- metadata +87 -143
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -3
- data/.autotest +0 -3
- data/.gemtest +0 -0
- data/.hoerc +0 -2
- data/.travis.yml +0 -22
- data/Contributing.rdoc +0 -64
- data/Gemfile +0 -20
- data/History.rdoc +0 -152
- metadata.gz.sig +0 -2
data/{License.rdoc → License.md}
RENAMED
File without changes
|
data/Manifest.txt
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
.autotest
|
2
|
-
.gemtest
|
3
|
-
.hoerc
|
4
1
|
.rspec
|
5
|
-
.
|
6
|
-
Contributing.
|
7
|
-
|
8
|
-
|
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
|
data/README.rdoc
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
= Diff::LCS
|
2
2
|
|
3
|
-
home ::
|
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.
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
#
|
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
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
19
|
+
class Gem::Specification #:nodoc:
|
20
|
+
def metadata=(*); end
|
20
21
|
|
21
|
-
|
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.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
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
|
data/autotest/discover.rb
CHANGED
data/bin/htmldiff
CHANGED
@@ -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
|
-
|
14
|
-
|
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],
|
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
data/lib/diff-lcs.rb
CHANGED
data/lib/diff/lcs.rb
CHANGED
@@ -1,76 +1,24 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Diff; end unless defined? Diff
|
4
|
-
|
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
|
-
#
|
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
|
-
#
|
64
|
-
#
|
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
|
-
#
|
73
|
-
#
|
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
|
-
#
|
87
|
-
#
|
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
|
-
#
|
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
|
-
# © 2000–2002 and the Smalltalk diff version by Mario I.
|
109
|
-
# Wolczko, copyright © 1993. Documentation includes work by
|
110
|
-
# Mark-Jason Dominus.
|
111
|
-
#
|
112
|
-
# == Licence
|
113
|
-
# Copyright © 2004–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.
|
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#
|
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
|
-
#
|
176
|
-
#
|
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
|
-
|
104
|
+
alias unpatch patch
|
181
105
|
|
182
|
-
# Attempts to patch +self+ with the provided +patchset+. A new sequence
|
183
|
-
#
|
184
|
-
#
|
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
|
-
#
|
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
|
-
#
|
209
|
-
#
|
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 |
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
303
|
-
#
|
304
|
-
#
|
305
|
-
#
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
309
|
-
#
|
310
|
-
#
|
311
|
-
#
|
312
|
-
#
|
313
|
-
#
|
314
|
-
#
|
315
|
-
# that
|
316
|
-
#
|
317
|
-
#
|
318
|
-
#
|
319
|
-
#
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
325
|
-
#
|
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
|
-
#
|
333
|
-
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
#
|
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
|
-
#
|
343
|
-
#
|
344
|
-
#
|
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
|
-
#
|
349
|
-
#
|
350
|
-
def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks
|
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
|
-
#
|
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
|
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
|
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
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
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
|
-
#
|
462
|
-
#
|
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
|
-
#
|
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
|
-
#
|
504
|
-
#
|
505
|
-
#
|
506
|
-
#
|
507
|
-
#
|
508
|
-
#
|
509
|
-
#
|
510
|
-
#
|
511
|
-
#
|
512
|
-
#
|
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
|
-
#
|
519
|
-
#
|
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
|
-
#
|
535
|
-
#
|
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
|
-
#
|
540
|
-
# and +
|
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
|
-
#
|
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
|
-
#
|
667
|
-
#
|
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
|
-
#
|
676
|
-
#
|
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
|
-
#
|
687
|
-
#
|
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
|
-
|
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.
|
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
|
-
|
741
|
-
|
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
|
-
|
758
|
-
|
689
|
+
bj += 1
|
690
|
+
ai += 1
|
759
691
|
|
760
|
-
|
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
|
-
|
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
|
-
|
710
|
+
bj += 1
|
779
711
|
|
780
|
-
|
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
|
-
#
|
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
|
-
#
|
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'
|