diff-lcs 1.4.4 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Contributing.md +3 -0
- data/History.md +219 -107
- data/License.md +6 -4
- data/Manifest.txt +15 -1
- data/Rakefile +81 -25
- data/bin/htmldiff +4 -4
- data/lib/diff/lcs/array.rb +1 -1
- data/lib/diff/lcs/backports.rb +2 -2
- data/lib/diff/lcs/block.rb +4 -4
- data/lib/diff/lcs/callbacks.rb +9 -7
- data/lib/diff/lcs/change.rb +19 -19
- data/lib/diff/lcs/htmldiff.rb +24 -16
- data/lib/diff/lcs/hunk.rb +35 -30
- data/lib/diff/lcs/internals.rb +24 -20
- data/lib/diff/lcs/ldiff.rb +37 -35
- data/lib/diff/lcs.rb +77 -75
- data/lib/diff-lcs.rb +1 -1
- data/spec/change_spec.rb +50 -50
- data/spec/diff_spec.rb +14 -14
- data/spec/fixtures/ldiff/output.diff.chef +4 -0
- data/spec/fixtures/ldiff/output.diff.chef-c +15 -0
- data/spec/fixtures/ldiff/output.diff.chef-e +3 -0
- data/spec/fixtures/ldiff/output.diff.chef-f +3 -0
- data/spec/fixtures/ldiff/output.diff.chef-u +9 -0
- data/spec/fixtures/ldiff/output.diff.chef2 +7 -0
- data/spec/fixtures/ldiff/output.diff.chef2-c +20 -0
- data/spec/fixtures/ldiff/output.diff.chef2-d +7 -0
- data/spec/fixtures/ldiff/output.diff.chef2-e +7 -0
- data/spec/fixtures/ldiff/output.diff.chef2-f +7 -0
- data/spec/fixtures/ldiff/output.diff.chef2-u +16 -0
- data/spec/fixtures/new-chef +4 -0
- data/spec/fixtures/new-chef2 +17 -0
- data/spec/fixtures/old-chef +4 -0
- data/spec/fixtures/old-chef2 +14 -0
- data/spec/hunk_spec.rb +19 -19
- data/spec/issues_spec.rb +48 -42
- data/spec/lcs_spec.rb +11 -11
- data/spec/ldiff_spec.rb +13 -11
- data/spec/patch_spec.rb +84 -84
- data/spec/sdiff_spec.rb +111 -109
- data/spec/spec_helper.rb +77 -76
- data/spec/traverse_balanced_spec.rb +191 -189
- data/spec/traverse_sequences_spec.rb +31 -33
- metadata +50 -23
- data/autotest/discover.rb +0 -3
data/Rakefile
CHANGED
@@ -1,63 +1,118 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "rubygems"
|
4
|
+
require "rspec"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "hoe"
|
7
|
+
|
8
|
+
# This is required until https://github.com/seattlerb/hoe/issues/112 is fixed
|
9
|
+
class Hoe
|
10
|
+
def with_config
|
11
|
+
config = Hoe::DEFAULT_CONFIG
|
12
|
+
|
13
|
+
rc = File.expand_path("~/.hoerc")
|
14
|
+
homeconfig = load_config(rc)
|
15
|
+
config = config.merge(homeconfig)
|
16
|
+
|
17
|
+
localconfig = load_config(File.expand_path(File.join(Dir.pwd, ".hoerc")))
|
18
|
+
config = config.merge(localconfig)
|
19
|
+
|
20
|
+
yield config, rc
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_config(name)
|
24
|
+
File.exist?(name) ? safe_load_yaml(name) : {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def safe_load_yaml(name)
|
28
|
+
return safe_load_yaml_file(name) if YAML.respond_to?(:safe_load_file)
|
29
|
+
|
30
|
+
data = IO.binread(name)
|
31
|
+
YAML.safe_load(data, permitted_classes: [Regexp])
|
32
|
+
rescue
|
33
|
+
YAML.safe_load(data, [Regexp])
|
34
|
+
end
|
35
|
+
|
36
|
+
def safe_load_yaml_file(name)
|
37
|
+
YAML.safe_load_file(name, permitted_classes: [Regexp])
|
38
|
+
rescue
|
39
|
+
YAML.safe_load_file(name, [Regexp])
|
40
|
+
end
|
41
|
+
end
|
6
42
|
|
7
43
|
Hoe.plugin :bundler
|
8
44
|
Hoe.plugin :doofus
|
9
45
|
Hoe.plugin :gemspec2
|
10
46
|
Hoe.plugin :git
|
11
47
|
|
12
|
-
if RUBY_VERSION <
|
13
|
-
class Array
|
48
|
+
if RUBY_VERSION < "1.9"
|
49
|
+
class Array # :nodoc:
|
14
50
|
def to_h
|
15
51
|
Hash[*flatten(1)]
|
16
52
|
end
|
17
53
|
end
|
18
54
|
|
19
|
-
class Gem::Specification
|
20
|
-
def metadata=(*)
|
55
|
+
class Gem::Specification # :nodoc:
|
56
|
+
def metadata=(*)
|
57
|
+
end
|
21
58
|
|
22
|
-
def default_value(*)
|
59
|
+
def default_value(*)
|
60
|
+
end
|
23
61
|
end
|
24
62
|
|
25
|
-
class Object
|
63
|
+
class Object # :nodoc:
|
26
64
|
def caller_locations(*)
|
27
65
|
[]
|
28
66
|
end
|
29
67
|
end
|
30
68
|
end
|
31
69
|
|
32
|
-
_spec = Hoe.spec
|
33
|
-
developer(
|
70
|
+
_spec = Hoe.spec "diff-lcs" do
|
71
|
+
developer("Austin Ziegler", "halostatue@gmail.com")
|
34
72
|
|
35
|
-
require_ruby_version
|
73
|
+
require_ruby_version ">= 1.8"
|
36
74
|
|
37
|
-
self.history_file =
|
38
|
-
self.readme_file =
|
39
|
-
self.licenses = [
|
75
|
+
self.history_file = "History.md"
|
76
|
+
self.readme_file = "README.rdoc"
|
77
|
+
self.licenses = ["MIT", "Artistic-2.0", "GPL-2.0-or-later"]
|
40
78
|
|
41
|
-
|
42
|
-
|
43
|
-
extra_dev_deps << [
|
44
|
-
extra_dev_deps << [
|
45
|
-
extra_dev_deps << [
|
46
|
-
extra_dev_deps << [
|
47
|
-
extra_dev_deps << [
|
79
|
+
spec_extras[:metadata] = ->(val) { val["rubygems_mfa_required"] = "true" }
|
80
|
+
|
81
|
+
extra_dev_deps << ["hoe", ">= 3.0", "< 5"]
|
82
|
+
extra_dev_deps << ["hoe-doofus", "~> 1.0"]
|
83
|
+
extra_dev_deps << ["hoe-gemspec2", "~> 1.1"]
|
84
|
+
extra_dev_deps << ["hoe-git2", "~> 1.7"]
|
85
|
+
extra_dev_deps << ["hoe-rubygems", "~> 1.0"]
|
86
|
+
extra_dev_deps << ["rspec", ">= 2.0", "< 4"]
|
87
|
+
extra_dev_deps << ["rake", ">= 10.0", "< 14"]
|
88
|
+
extra_dev_deps << ["rdoc", ">= 6.3.1", "< 7"]
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "Run all specifications"
|
92
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
93
|
+
rspec_dirs = %w[spec lib].join(":")
|
94
|
+
t.rspec_opts = ["-I#{rspec_dirs}"]
|
48
95
|
end
|
49
96
|
|
50
|
-
|
97
|
+
Rake::Task["spec"].actions.uniq! { |a| a.source_location }
|
98
|
+
|
99
|
+
# standard:disable Style/HashSyntax
|
100
|
+
task :default => :spec unless Rake::Task["default"].prereqs.include?("spec")
|
101
|
+
task :test => :spec unless Rake::Task["test"].prereqs.include?("spec")
|
102
|
+
# standard:enable Style/HashSyntax
|
103
|
+
|
104
|
+
if RUBY_VERSION >= "2.0" && RUBY_ENGINE == "ruby"
|
51
105
|
namespace :spec do
|
52
106
|
desc "Runs test coverage. Only works Ruby 2.0+ and assumes 'simplecov' is installed."
|
53
107
|
task :coverage do
|
54
|
-
ENV[
|
55
|
-
Rake::Task[
|
108
|
+
ENV["COVERAGE"] = "yes"
|
109
|
+
Rake::Task["spec"].execute
|
56
110
|
end
|
57
111
|
end
|
58
112
|
end
|
59
113
|
|
60
114
|
task :ruby18 do
|
115
|
+
# standard:disable Layout/HeredocIndentation
|
61
116
|
puts <<-MESSAGE
|
62
117
|
You are starting a barebones Ruby 1.8 docker environment. You will need to
|
63
118
|
do the following:
|
@@ -70,5 +125,6 @@ do the following:
|
|
70
125
|
Don't forget to restore your Gemfile.lock after testing.
|
71
126
|
|
72
127
|
MESSAGE
|
128
|
+
# standard:enable Layout/HeredocIndentation
|
73
129
|
sh "docker run -it --rm -v #{Dir.pwd}:/root/diff-lcs bellbind/docker-ruby18-rails2 bash -l"
|
74
130
|
end
|
data/bin/htmldiff
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#! /usr/bin/env ruby -w
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require "diff/lcs"
|
5
|
+
require "diff/lcs/htmldiff"
|
6
6
|
|
7
7
|
begin
|
8
|
-
require
|
8
|
+
require "text/format"
|
9
9
|
rescue LoadError
|
10
10
|
Diff::LCS::HTMLDiff.can_expand_tabs = false
|
11
11
|
end
|
@@ -24,7 +24,7 @@ options = { :title => "diff #{ARGV[0]} #{ARGV[1]}" }
|
|
24
24
|
htmldiff = Diff::LCS::HTMLDiff.new(left, right, options)
|
25
25
|
|
26
26
|
if ARGV[2]
|
27
|
-
File.open(ARGV[2],
|
27
|
+
File.open(ARGV[2], "w") do |f|
|
28
28
|
htmldiff.options[:output] = f
|
29
29
|
htmldiff.run
|
30
30
|
end
|
data/lib/diff/lcs/array.rb
CHANGED
data/lib/diff/lcs/backports.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
unless 0.respond_to?(:positive?)
|
4
|
-
class Fixnum #
|
4
|
+
class Fixnum # standard:disable Lint/UnifiedInteger
|
5
5
|
def positive?
|
6
|
-
self > 0
|
6
|
+
self > 0
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
data/lib/diff/lcs/block.rb
CHANGED
@@ -25,13 +25,13 @@ class Diff::LCS::Block
|
|
25
25
|
def op
|
26
26
|
case [@remove.empty?, @insert.empty?]
|
27
27
|
when [false, false]
|
28
|
-
|
28
|
+
"!"
|
29
29
|
when [false, true]
|
30
|
-
|
30
|
+
"-"
|
31
31
|
when [true, false]
|
32
|
-
|
32
|
+
"+"
|
33
33
|
else # [true, true]
|
34
|
-
|
34
|
+
"^"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
data/lib/diff/lcs/callbacks.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "diff/lcs/change"
|
4
4
|
|
5
|
-
module Diff::LCS
|
5
|
+
module Diff::LCS
|
6
6
|
# This callback object implements the default set of callback events,
|
7
7
|
# which only returns the event itself. Note that #finished_a and
|
8
8
|
# #finished_b are not implemented -- I haven't yet figured out where they
|
@@ -50,7 +50,9 @@ module Diff::LCS # rubocop:disable Style/Documentation
|
|
50
50
|
BalancedCallbacks = DefaultCallbacks
|
51
51
|
|
52
52
|
def self.callbacks_for(callbacks)
|
53
|
-
callbacks.new
|
53
|
+
callbacks.new
|
54
|
+
rescue
|
55
|
+
callbacks
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
@@ -107,7 +109,7 @@ class Diff::LCS::DiffCallbacks
|
|
107
109
|
# Returns the difference set collected during the diff process.
|
108
110
|
attr_reader :diffs
|
109
111
|
|
110
|
-
def initialize # :yields self
|
112
|
+
def initialize # :yields: self
|
111
113
|
@hunk = []
|
112
114
|
@diffs = []
|
113
115
|
|
@@ -131,11 +133,11 @@ class Diff::LCS::DiffCallbacks
|
|
131
133
|
end
|
132
134
|
|
133
135
|
def discard_a(event)
|
134
|
-
@hunk << Diff::LCS::Change.new(
|
136
|
+
@hunk << Diff::LCS::Change.new("-", event.old_position, event.old_element)
|
135
137
|
end
|
136
138
|
|
137
139
|
def discard_b(event)
|
138
|
-
@hunk << Diff::LCS::Change.new(
|
140
|
+
@hunk << Diff::LCS::Change.new("+", event.new_position, event.new_element)
|
139
141
|
end
|
140
142
|
|
141
143
|
def finish_hunk
|
@@ -302,7 +304,7 @@ class Diff::LCS::SDiffCallbacks
|
|
302
304
|
# Returns the difference set collected during the diff process.
|
303
305
|
attr_reader :diffs
|
304
306
|
|
305
|
-
def initialize
|
307
|
+
def initialize # :yields: self
|
306
308
|
@diffs = []
|
307
309
|
yield self if block_given?
|
308
310
|
end
|
data/lib/diff/lcs/change.rb
CHANGED
@@ -10,7 +10,7 @@ class Diff::LCS::Change
|
|
10
10
|
# (no change), '!' (changed), '<' (tail changes from first sequence), or
|
11
11
|
# '>' (tail changes from second sequence). The last two ('<>') are only
|
12
12
|
# found with Diff::LCS::diff and Diff::LCS::sdiff.
|
13
|
-
VALID_ACTIONS = %w
|
13
|
+
VALID_ACTIONS = %w[+ - = ! > <].freeze
|
14
14
|
|
15
15
|
def self.valid_action?(action)
|
16
16
|
VALID_ACTIONS.include? action
|
@@ -28,7 +28,7 @@ class Diff::LCS::Change
|
|
28
28
|
@action, @position, @element = *args
|
29
29
|
|
30
30
|
fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
|
31
|
-
fail
|
31
|
+
fail "Invalid Position Type" unless @position.is_a? IntClass
|
32
32
|
end
|
33
33
|
|
34
34
|
def inspect(*_args)
|
@@ -39,7 +39,7 @@ class Diff::LCS::Change
|
|
39
39
|
[@action, @position, @element]
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
alias_method :to_ary, :to_a
|
43
43
|
|
44
44
|
def self.from_a(arr)
|
45
45
|
arr = arr.flatten(1)
|
@@ -49,7 +49,7 @@ class Diff::LCS::Change
|
|
49
49
|
when 3
|
50
50
|
Diff::LCS::Change.new(*(arr[0...3]))
|
51
51
|
else
|
52
|
-
fail
|
52
|
+
fail "Invalid change array format provided."
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -70,27 +70,27 @@ class Diff::LCS::Change
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def adding?
|
73
|
-
@action ==
|
73
|
+
@action == "+"
|
74
74
|
end
|
75
75
|
|
76
76
|
def deleting?
|
77
|
-
@action ==
|
77
|
+
@action == "-"
|
78
78
|
end
|
79
79
|
|
80
80
|
def unchanged?
|
81
|
-
@action ==
|
81
|
+
@action == "="
|
82
82
|
end
|
83
83
|
|
84
84
|
def changed?
|
85
|
-
@action ==
|
85
|
+
@action == "!"
|
86
86
|
end
|
87
87
|
|
88
88
|
def finished_a?
|
89
|
-
@action ==
|
89
|
+
@action == ">"
|
90
90
|
end
|
91
91
|
|
92
92
|
def finished_b?
|
93
|
-
@action ==
|
93
|
+
@action == "<"
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -115,8 +115,8 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
115
115
|
@action, @old_position, @old_element, @new_position, @new_element = *args
|
116
116
|
|
117
117
|
fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
|
118
|
-
fail
|
119
|
-
fail
|
118
|
+
fail "Invalid (Old) Position Type" unless @old_position.nil? || @old_position.is_a?(IntClass)
|
119
|
+
fail "Invalid (New) Position Type" unless @new_position.nil? || @new_position.is_a?(IntClass)
|
120
120
|
end
|
121
121
|
|
122
122
|
def to_a
|
@@ -127,7 +127,7 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
127
127
|
]
|
128
128
|
end
|
129
129
|
|
130
|
-
|
130
|
+
alias_method :to_ary, :to_a
|
131
131
|
|
132
132
|
def self.from_a(arr)
|
133
133
|
Diff::LCS::Change.from_a(arr)
|
@@ -139,15 +139,15 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
|
|
139
139
|
ea = event.to_a
|
140
140
|
|
141
141
|
case ea[0]
|
142
|
-
when
|
142
|
+
when "-"
|
143
143
|
ea[2][1] = nil
|
144
|
-
when
|
145
|
-
ea[0] =
|
144
|
+
when "<"
|
145
|
+
ea[0] = "-"
|
146
146
|
ea[2][1] = nil
|
147
|
-
when
|
147
|
+
when "+"
|
148
148
|
ea[1][1] = nil
|
149
|
-
when
|
150
|
-
ea[0] =
|
149
|
+
when ">"
|
150
|
+
ea[0] = "+"
|
151
151
|
ea[1][1] = nil
|
152
152
|
end
|
153
153
|
|
data/lib/diff/lcs/htmldiff.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "cgi"
|
4
4
|
|
5
5
|
# Produce a simple HTML diff view.
|
6
6
|
class Diff::LCS::HTMLDiff
|
7
7
|
class << self
|
8
|
-
attr_accessor :can_expand_tabs
|
8
|
+
attr_accessor :can_expand_tabs # :nodoc:
|
9
9
|
end
|
10
10
|
self.can_expand_tabs = true
|
11
11
|
|
12
|
-
class Callbacks
|
12
|
+
class Callbacks # :nodoc:
|
13
13
|
attr_accessor :output
|
14
14
|
attr_accessor :match_class
|
15
15
|
attr_accessor :only_a_class
|
@@ -19,14 +19,14 @@ class Diff::LCS::HTMLDiff
|
|
19
19
|
@output = output
|
20
20
|
options ||= {}
|
21
21
|
|
22
|
-
@match_class = options[:match_class] ||
|
23
|
-
@only_a_class = options[:only_a_class] ||
|
24
|
-
@only_b_class = options[:only_b_class] ||
|
22
|
+
@match_class = options[:match_class] || "match"
|
23
|
+
@only_a_class = options[:only_a_class] || "only_a"
|
24
|
+
@only_b_class = options[:only_b_class] || "only_b"
|
25
25
|
end
|
26
26
|
|
27
27
|
def htmlize(element, css_class)
|
28
|
-
element =
|
29
|
-
%
|
28
|
+
element = " " if element.empty?
|
29
|
+
%(<pre class="#{__send__(css_class)}">#{element}</pre>\n)
|
30
30
|
end
|
31
31
|
private :htmlize
|
32
32
|
|
@@ -46,13 +46,16 @@ class Diff::LCS::HTMLDiff
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
# standard:disable Style/HashSyntax
|
49
50
|
DEFAULT_OPTIONS = {
|
50
51
|
:expand_tabs => nil,
|
51
52
|
:output => nil,
|
52
53
|
:css => nil,
|
53
54
|
:title => nil
|
54
55
|
}.freeze
|
56
|
+
# standard:enable Style/HashSyntax
|
55
57
|
|
58
|
+
# standard:disable Layout/HeredocIndentation
|
56
59
|
DEFAULT_CSS = <<-CSS
|
57
60
|
body { margin: 0; }
|
58
61
|
.diff
|
@@ -86,11 +89,12 @@ pre
|
|
86
89
|
}
|
87
90
|
h1 { margin-left: 2em; }
|
88
91
|
CSS
|
92
|
+
# standard:enable Layout/HeredocIndentation
|
89
93
|
|
90
94
|
def initialize(left, right, options = nil)
|
91
|
-
@left
|
92
|
-
@right
|
93
|
-
@options
|
95
|
+
@left = left
|
96
|
+
@right = right
|
97
|
+
@options = options
|
94
98
|
|
95
99
|
@options = DEFAULT_OPTIONS.dup if @options.nil?
|
96
100
|
end
|
@@ -103,7 +107,7 @@ h1 { margin-left: 2em; }
|
|
103
107
|
|
104
108
|
@options[:css] ||= DEFAULT_CSS.dup
|
105
109
|
|
106
|
-
@options[:title] ||=
|
110
|
+
@options[:title] ||= "diff"
|
107
111
|
end
|
108
112
|
private :verify_options
|
109
113
|
|
@@ -116,13 +120,14 @@ h1 { margin-left: 2em; }
|
|
116
120
|
formatter = Text::Format.new
|
117
121
|
formatter.tabstop = @options[:expand_tabs]
|
118
122
|
|
119
|
-
@left.map!
|
120
|
-
@right.map!
|
123
|
+
@left.map! { |line| formatter.expand(line.chomp) }
|
124
|
+
@right.map! { |line| formatter.expand(line.chomp) }
|
121
125
|
end
|
122
126
|
|
123
|
-
@left.map!
|
124
|
-
@right.map!
|
127
|
+
@left.map! { |line| CGI.escapeHTML(line.chomp) }
|
128
|
+
@right.map! { |line| CGI.escapeHTML(line.chomp) }
|
125
129
|
|
130
|
+
# standard:disable Layout/HeredocIndentation
|
126
131
|
@options[:output] << <<-OUTPUT
|
127
132
|
<html>
|
128
133
|
<head>
|
@@ -137,14 +142,17 @@ h1 { margin-left: 2em; }
|
|
137
142
|
<span class="only_b">Only in New</span></p>
|
138
143
|
<div class="diff">
|
139
144
|
OUTPUT
|
145
|
+
# standard:enable Layout/HeredocIndentation
|
140
146
|
|
141
147
|
callbacks = Callbacks.new(@options[:output])
|
142
148
|
Diff::LCS.traverse_sequences(@left, @right, callbacks)
|
143
149
|
|
150
|
+
# standard:disable Layout/HeredocIndentation
|
144
151
|
@options[:output] << <<-OUTPUT
|
145
152
|
</div>
|
146
153
|
</body>
|
147
154
|
</html>
|
148
155
|
OUTPUT
|
156
|
+
# standard:enable Layout/HeredocIndentation
|
149
157
|
end
|
150
158
|
end
|