diff-lcs 1.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/Contributing.md +84 -48
  3. data/History.md +334 -154
  4. data/Manifest.txt +23 -1
  5. data/README.rdoc +10 -10
  6. data/Rakefile +85 -21
  7. data/bin/htmldiff +7 -4
  8. data/bin/ldiff +4 -1
  9. data/lib/diff/lcs/array.rb +1 -1
  10. data/lib/diff/lcs/backports.rb +9 -0
  11. data/lib/diff/lcs/block.rb +1 -1
  12. data/lib/diff/lcs/callbacks.rb +15 -12
  13. data/lib/diff/lcs/change.rb +30 -37
  14. data/lib/diff/lcs/htmldiff.rb +17 -16
  15. data/lib/diff/lcs/hunk.rb +156 -74
  16. data/lib/diff/lcs/internals.rb +43 -42
  17. data/lib/diff/lcs/ldiff.rb +46 -42
  18. data/lib/diff/lcs/string.rb +1 -1
  19. data/lib/diff/lcs.rb +188 -174
  20. data/lib/diff-lcs.rb +1 -1
  21. data/spec/change_spec.rb +31 -7
  22. data/spec/diff_spec.rb +16 -12
  23. data/spec/fixtures/aX +1 -0
  24. data/spec/fixtures/bXaX +1 -0
  25. data/spec/fixtures/ldiff/output.diff +4 -0
  26. data/spec/fixtures/ldiff/output.diff-c +7 -0
  27. data/spec/fixtures/ldiff/output.diff-e +3 -0
  28. data/spec/fixtures/ldiff/output.diff-f +3 -0
  29. data/spec/fixtures/ldiff/output.diff-u +5 -0
  30. data/spec/fixtures/ldiff/output.diff.chef +4 -0
  31. data/spec/fixtures/ldiff/output.diff.chef-c +15 -0
  32. data/spec/fixtures/ldiff/output.diff.chef-e +3 -0
  33. data/spec/fixtures/ldiff/output.diff.chef-f +3 -0
  34. data/spec/fixtures/ldiff/output.diff.chef-u +9 -0
  35. data/spec/fixtures/ldiff/output.diff.chef2 +7 -0
  36. data/spec/fixtures/ldiff/output.diff.chef2-c +20 -0
  37. data/spec/fixtures/ldiff/output.diff.chef2-d +7 -0
  38. data/spec/fixtures/ldiff/output.diff.chef2-e +7 -0
  39. data/spec/fixtures/ldiff/output.diff.chef2-f +7 -0
  40. data/spec/fixtures/ldiff/output.diff.chef2-u +16 -0
  41. data/spec/fixtures/new-chef +4 -0
  42. data/spec/fixtures/new-chef2 +17 -0
  43. data/spec/fixtures/old-chef +4 -0
  44. data/spec/fixtures/old-chef2 +14 -0
  45. data/spec/hunk_spec.rb +37 -26
  46. data/spec/issues_spec.rb +115 -10
  47. data/spec/lcs_spec.rb +10 -10
  48. data/spec/ldiff_spec.rb +71 -31
  49. data/spec/patch_spec.rb +93 -99
  50. data/spec/sdiff_spec.rb +89 -89
  51. data/spec/spec_helper.rb +118 -65
  52. data/spec/traverse_balanced_spec.rb +173 -173
  53. data/spec/traverse_sequences_spec.rb +29 -31
  54. metadata +54 -33
  55. data/autotest/discover.rb +0 -1
data/Rakefile CHANGED
@@ -1,57 +1,121 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rspec'
5
+ require 'rspec/core/rake_task'
5
6
  require 'hoe'
6
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
42
+
7
43
  Hoe.plugin :bundler
8
44
  Hoe.plugin :doofus
9
- Hoe.plugin :email unless ENV['CI'] or ENV['TRAVIS']
10
45
  Hoe.plugin :gemspec2
11
46
  Hoe.plugin :git
12
- Hoe.plugin :travis
13
47
 
14
- spec = Hoe.spec 'diff-lcs' do
48
+ if RUBY_VERSION < '1.9'
49
+ class Array #:nodoc:
50
+ def to_h
51
+ Hash[*flatten(1)]
52
+ end
53
+ end
54
+
55
+ class Gem::Specification #:nodoc:
56
+ def metadata=(*); end
57
+
58
+ def default_value(*); end
59
+ end
60
+
61
+ class Object #:nodoc:
62
+ def caller_locations(*)
63
+ []
64
+ end
65
+ end
66
+ end
67
+
68
+ _spec = Hoe.spec 'diff-lcs' do
15
69
  developer('Austin Ziegler', 'halostatue@gmail.com')
16
70
 
17
71
  require_ruby_version '>= 1.8'
18
72
 
19
73
  self.history_file = 'History.md'
20
74
  self.readme_file = 'README.rdoc'
21
- self.licenses = [ 'MIT', 'Artistic-2.0', 'GPL-2.0+' ]
75
+ self.licenses = ['MIT', 'Artistic-2.0', 'GPL-2.0+']
22
76
 
23
77
  extra_dev_deps << ['hoe-doofus', '~> 1.0']
24
78
  extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
25
79
  extra_dev_deps << ['hoe-git', '~> 1.6']
26
80
  extra_dev_deps << ['hoe-rubygems', '~> 1.0']
27
- extra_dev_deps << ['hoe-travis', '~> 1.2']
28
81
  extra_dev_deps << ['rspec', '>= 2.0', '< 4']
29
- extra_dev_deps << ['rake', '>= 10.0', '< 12']
30
- extra_dev_deps << ['rdoc', '>= 0']
82
+ extra_dev_deps << ['rake', '>= 10.0', '< 14']
83
+ extra_dev_deps << ['rdoc', '>= 6.3.1', '< 7']
31
84
  end
32
85
 
33
- unless Rake::Task.task_defined? :test
34
- task :test => :spec
35
- Rake::Task['travis'].prerequisites.replace(%w(spec))
86
+ desc "Run all specifications"
87
+ RSpec::Core::RakeTask.new(:spec) do |t|
88
+ rspec_dirs = %w(spec lib).join(":")
89
+ t.rspec_opts = ["-I#{rspec_dirs}"]
36
90
  end
37
91
 
92
+ Rake::Task["spec"].actions.uniq! { |a| a.source_location }
93
+
94
+ task :default => :spec unless Rake::Task["default"].prereqs.include?("spec")
95
+ task :test => :spec unless Rake::Task["test"].prereqs.include?("spec")
96
+
38
97
  if RUBY_VERSION >= '2.0' && RUBY_ENGINE == 'ruby'
39
98
  namespace :spec do
40
- task :coveralls do
41
- if ENV['CI'] or ENV['TRAVIS']
42
- ENV['COVERALLS'] = 'yes'
43
- Rake::Task['spec'].execute
44
- else
45
- Rake::Task['spec:coverage'].execute
46
- end
47
- end
48
-
49
99
  desc "Runs test coverage. Only works Ruby 2.0+ and assumes 'simplecov' is installed."
50
100
  task :coverage do
51
101
  ENV['COVERAGE'] = 'yes'
52
102
  Rake::Task['spec'].execute
53
103
  end
54
104
  end
105
+ end
106
+
107
+ task :ruby18 do
108
+ puts <<-MESSAGE
109
+ You are starting a barebones Ruby 1.8 docker environment. You will need to
110
+ do the following:
111
+
112
+ - mv Gemfile.lock{,.v2}
113
+ - gem install bundler --version 1.17.2 --no-ri --no-rdoc
114
+ - ruby -S bundle
115
+ - rake
116
+
117
+ Don't forget to restore your Gemfile.lock after testing.
55
118
 
56
- # Rake::Task['travis'].prerequisites.replace(%w(spec:coveralls))
119
+ MESSAGE
120
+ sh "docker run -it --rm -v #{Dir.pwd}:/root/diff-lcs bellbind/docker-ruby18-rails2 bash -l"
57
121
  end
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
- $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,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'diff/lcs'
4
4
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless 0.respond_to?(:positive?)
4
+ class Fixnum # rubocop:disable Lint/UnifiedInteger, Style/Documentation
5
+ def positive?
6
+ self > 0 # rubocop:disable Style/NumericPredicate
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  # A block is an operation removing, adding, or changing a group of items.
4
4
  # Basically, this is just a list of changes, where each change adds or
@@ -1,8 +1,8 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'diff/lcs/change'
4
4
 
5
- module Diff::LCS
5
+ module Diff::LCS # rubocop:disable Style/Documentation
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
@@ -17,14 +17,17 @@ module Diff::LCS
17
17
  def match(event)
18
18
  event
19
19
  end
20
+
20
21
  # Called when the old value is discarded in favour of the new value.
21
22
  def discard_a(event)
22
23
  event
23
24
  end
25
+
24
26
  # Called when the new value is discarded in favour of the old value.
25
27
  def discard_b(event)
26
28
  event
27
29
  end
30
+
28
31
  # Called when both the old and new values have changed.
29
32
  def change(event)
30
33
  event
@@ -108,12 +111,12 @@ class Diff::LCS::DiffCallbacks
108
111
  @hunk = []
109
112
  @diffs = []
110
113
 
111
- if block_given?
112
- begin
113
- yield self
114
- ensure
115
- self.finish
116
- end
114
+ return unless block_given?
115
+
116
+ begin
117
+ yield self
118
+ ensure
119
+ finish
117
120
  end
118
121
  end
119
122
 
@@ -123,7 +126,7 @@ class Diff::LCS::DiffCallbacks
123
126
  finish_hunk
124
127
  end
125
128
 
126
- def match(event)
129
+ def match(_event)
127
130
  finish_hunk
128
131
  end
129
132
 
@@ -190,7 +193,7 @@ end
190
193
  # Diff::LCS::SDiffCallbacks. They may be compared as:
191
194
  #
192
195
  # s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" }
193
- # c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten
196
+ # c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten(1)
194
197
  #
195
198
  # s == c # -> true
196
199
  #
@@ -241,7 +244,7 @@ end
241
244
  # will compute and display the necessary components to show two sequences
242
245
  # and their minimized differences side by side, just like the Unix utility
243
246
  # +sdiff+.
244
- #
247
+ #
245
248
  # same same
246
249
  # before | after
247
250
  # old < -
@@ -270,7 +273,7 @@ end
270
273
  # Diff::LCS::ContextDiffCallbacks. They may be compared as:
271
274
  #
272
275
  # s = Diff::LCS.sdiff(seq1, seq2).reject { |e| e.action == "=" }
273
- # c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten
276
+ # c = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks).flatten(1)
274
277
  #
275
278
  # s == c # -> true
276
279
  #
@@ -1,16 +1,16 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  # Represents a simplistic (non-contextual) change. Represents the removal or
4
4
  # addition of an element from either the old or the new sequenced
5
5
  # enumerable.
6
6
  class Diff::LCS::Change
7
- IntClass = 1.class # Fixnum is deprecated in Ruby 2.4
7
+ IntClass = 1.class # Fixnum is deprecated in Ruby 2.4 # rubocop:disable Naming/ConstantName
8
8
 
9
9
  # The only actions valid for changes are '+' (add), '-' (delete), '='
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
@@ -27,20 +27,20 @@ class Diff::LCS::Change
27
27
  def initialize(*args)
28
28
  @action, @position, @element = *args
29
29
 
30
- unless Diff::LCS::Change.valid_action?(@action)
31
- raise "Invalid Change Action '#{@action}'"
32
- end
33
- raise "Invalid Position Type" unless @position.kind_of? IntClass
30
+ fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
31
+ fail 'Invalid Position Type' unless @position.kind_of? IntClass
34
32
  end
35
33
 
36
- def inspect
37
- to_a.inspect
34
+ def inspect(*_args)
35
+ "#<#{self.class}: #{to_a.inspect}>"
38
36
  end
39
37
 
40
38
  def to_a
41
- [ @action, @position, @element ]
39
+ [@action, @position, @element]
42
40
  end
43
41
 
42
+ alias to_ary to_a
43
+
44
44
  def self.from_a(arr)
45
45
  arr = arr.flatten(1)
46
46
  case arr.size
@@ -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
- raise "Invalid change array format provided."
52
+ fail 'Invalid change array format provided.'
53
53
  end
54
54
  end
55
55
 
@@ -57,15 +57,15 @@ class Diff::LCS::Change
57
57
 
58
58
  def ==(other)
59
59
  (self.class == other.class) and
60
- (self.action == other.action) and
61
- (self.position == other.position) and
62
- (self.element == other.element)
60
+ (action == other.action) and
61
+ (position == other.position) and
62
+ (element == other.element)
63
63
  end
64
64
 
65
65
  def <=>(other)
66
- r = self.action <=> other.action
67
- r = self.position <=> other.position if r.zero?
68
- r = self.element <=> other.element if r.zero?
66
+ r = action <=> other.action
67
+ r = position <=> other.position if r.zero?
68
+ r = element <=> other.element if r.zero?
69
69
  r
70
70
  end
71
71
 
@@ -114,27 +114,20 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
114
114
  def initialize(*args)
115
115
  @action, @old_position, @old_element, @new_position, @new_element = *args
116
116
 
117
- unless Diff::LCS::Change.valid_action?(@action)
118
- raise "Invalid Change Action '#{@action}'"
119
- end
120
- unless @old_position.nil? or @old_position.kind_of? IntClass
121
- raise "Invalid (Old) Position Type"
122
- end
123
- unless @new_position.nil? or @new_position.kind_of? IntClass
124
- raise "Invalid (New) Position Type"
125
- end
117
+ fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
118
+ fail 'Invalid (Old) Position Type' unless @old_position.nil? or @old_position.kind_of? IntClass
119
+ fail 'Invalid (New) Position Type' unless @new_position.nil? or @new_position.kind_of? IntClass
126
120
  end
127
121
 
128
122
  def to_a
129
- [ @action,
130
- [ @old_position, @old_element ],
131
- [ @new_position, @new_element ]
123
+ [
124
+ @action,
125
+ [@old_position, @old_element],
126
+ [@new_position, @new_element]
132
127
  ]
133
128
  end
134
129
 
135
- def inspect(*args)
136
- to_a.inspect
137
- end
130
+ alias to_ary to_a
138
131
 
139
132
  def self.from_a(arr)
140
133
  Diff::LCS::Change.from_a(arr)
@@ -163,11 +156,11 @@ class Diff::LCS::ContextChange < Diff::LCS::Change
163
156
 
164
157
  def ==(other)
165
158
  (self.class == other.class) and
166
- (@action == other.action) and
167
- (@old_position == other.old_position) and
168
- (@new_position == other.new_position) and
169
- (@old_element == other.old_element) and
170
- (@new_element == other.new_element)
159
+ (@action == other.action) and
160
+ (@old_position == other.old_position) and
161
+ (@new_position == other.new_position) and
162
+ (@old_element == other.old_element) and
163
+ (@new_element == other.new_element)
171
164
  end
172
165
 
173
166
  def <=>(other)
@@ -1,14 +1,15 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'cgi'
4
4
 
5
+ # Produce a simple HTML diff view.
5
6
  class Diff::LCS::HTMLDiff
6
7
  class << self
7
8
  attr_accessor :can_expand_tabs #:nodoc:
8
9
  end
9
10
  self.can_expand_tabs = true
10
11
 
11
- class Callbacks
12
+ class Callbacks #:nodoc:
12
13
  attr_accessor :output
13
14
  attr_accessor :match_class
14
15
  attr_accessor :only_a_class
@@ -18,14 +19,14 @@ class Diff::LCS::HTMLDiff
18
19
  @output = output
19
20
  options ||= {}
20
21
 
21
- @match_class = options[:match_class] || "match"
22
- @only_a_class = options[:only_a_class] || "only_a"
23
- @only_b_class = options[:only_b_class] || "only_b"
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'
24
25
  end
25
26
 
26
27
  def htmlize(element, css_class)
27
- element = "&nbsp;" if element.empty?
28
- %Q|<pre class="#{__send__(css_class)}">#{element}</pre>\n|
28
+ element = '&nbsp;' if element.empty?
29
+ %Q(<pre class="#{__send__(css_class)}">#{element}</pre>\n)
29
30
  end
30
31
  private :htmlize
31
32
 
@@ -49,8 +50,8 @@ class Diff::LCS::HTMLDiff
49
50
  :expand_tabs => nil,
50
51
  :output => nil,
51
52
  :css => nil,
52
- :title => nil,
53
- }
53
+ :title => nil
54
+ }.freeze
54
55
 
55
56
  DEFAULT_CSS = <<-CSS
56
57
  body { margin: 0; }
@@ -96,13 +97,13 @@ h1 { margin-left: 2em; }
96
97
 
97
98
  def verify_options
98
99
  @options[:expand_tabs] ||= 4
99
- @options[:expand_tabs] = 4 if @options[:expand_tabs] < 0
100
+ @options[:expand_tabs] = 4 if @options[:expand_tabs].negative?
100
101
 
101
102
  @options[:output] ||= $stdout
102
103
 
103
104
  @options[:css] ||= DEFAULT_CSS.dup
104
105
 
105
- @options[:title] ||= "diff"
106
+ @options[:title] ||= 'diff'
106
107
  end
107
108
  private :verify_options
108
109
 
@@ -111,16 +112,16 @@ h1 { margin-left: 2em; }
111
112
  def run
112
113
  verify_options
113
114
 
114
- if @options[:expand_tabs] > 0 && self.class.can_expand_tabs
115
+ if @options[:expand_tabs].positive? && self.class.can_expand_tabs
115
116
  formatter = Text::Format.new
116
117
  formatter.tabstop = @options[:expand_tabs]
117
118
 
118
- @left.map! { |line| formatter.expand(line.chomp) }
119
- @right.map! { |line| formatter.expand(line.chomp) }
119
+ @left.map! do |line| formatter.expand(line.chomp) end
120
+ @right.map! do |line| formatter.expand(line.chomp) end
120
121
  end
121
122
 
122
- @left.map! { |line| CGI.escapeHTML(line.chomp) }
123
- @right.map! { |line| CGI.escapeHTML(line.chomp) }
123
+ @left.map! do |line| CGI.escapeHTML(line.chomp) end
124
+ @right.map! do |line| CGI.escapeHTML(line.chomp) end
124
125
 
125
126
  @options[:output] << <<-OUTPUT
126
127
  <html>