diff-lcs 1.1.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/Code-of-Conduct.md +74 -0
  4. data/Contributing.md +119 -0
  5. data/History.md +400 -0
  6. data/{License.rdoc → License.md} +6 -5
  7. data/Manifest.txt +36 -4
  8. data/README.rdoc +35 -23
  9. data/Rakefile +106 -11
  10. data/bin/htmldiff +7 -4
  11. data/bin/ldiff +4 -1
  12. data/docs/COPYING.txt +21 -22
  13. data/docs/artistic.txt +127 -0
  14. data/lib/diff/lcs/array.rb +1 -15
  15. data/lib/diff/lcs/backports.rb +9 -0
  16. data/lib/diff/lcs/block.rb +4 -18
  17. data/lib/diff/lcs/callbacks.rb +233 -230
  18. data/lib/diff/lcs/change.rb +114 -109
  19. data/lib/diff/lcs/htmldiff.rb +17 -18
  20. data/lib/diff/lcs/hunk.rb +232 -116
  21. data/lib/diff/lcs/internals.rb +308 -0
  22. data/lib/diff/lcs/ldiff.rb +138 -177
  23. data/lib/diff/lcs/string.rb +1 -15
  24. data/lib/diff/lcs.rb +597 -963
  25. data/lib/diff-lcs.rb +1 -3
  26. data/spec/change_spec.rb +89 -0
  27. data/spec/diff_spec.rb +32 -16
  28. data/spec/fixtures/aX +1 -0
  29. data/spec/fixtures/bXaX +1 -0
  30. data/spec/fixtures/ds1.csv +50 -0
  31. data/spec/fixtures/ds2.csv +51 -0
  32. data/spec/fixtures/ldiff/output.diff +4 -0
  33. data/spec/fixtures/ldiff/output.diff-c +7 -0
  34. data/spec/fixtures/ldiff/output.diff-e +3 -0
  35. data/spec/fixtures/ldiff/output.diff-f +3 -0
  36. data/spec/fixtures/ldiff/output.diff-u +5 -0
  37. data/spec/fixtures/ldiff/output.diff.chef +4 -0
  38. data/spec/fixtures/ldiff/output.diff.chef-c +15 -0
  39. data/spec/fixtures/ldiff/output.diff.chef-e +3 -0
  40. data/spec/fixtures/ldiff/output.diff.chef-f +3 -0
  41. data/spec/fixtures/ldiff/output.diff.chef-u +9 -0
  42. data/spec/fixtures/ldiff/output.diff.chef2 +7 -0
  43. data/spec/fixtures/ldiff/output.diff.chef2-c +20 -0
  44. data/spec/fixtures/ldiff/output.diff.chef2-d +7 -0
  45. data/spec/fixtures/ldiff/output.diff.chef2-e +7 -0
  46. data/spec/fixtures/ldiff/output.diff.chef2-f +7 -0
  47. data/spec/fixtures/ldiff/output.diff.chef2-u +16 -0
  48. data/spec/fixtures/new-chef +4 -0
  49. data/spec/fixtures/new-chef2 +17 -0
  50. data/spec/fixtures/old-chef +4 -0
  51. data/spec/fixtures/old-chef2 +14 -0
  52. data/spec/hunk_spec.rb +83 -0
  53. data/spec/issues_spec.rb +154 -0
  54. data/spec/lcs_spec.rb +36 -16
  55. data/spec/ldiff_spec.rb +87 -0
  56. data/spec/patch_spec.rb +198 -172
  57. data/spec/sdiff_spec.rb +99 -89
  58. data/spec/spec_helper.rb +149 -59
  59. data/spec/traverse_balanced_spec.rb +191 -167
  60. data/spec/traverse_sequences_spec.rb +105 -51
  61. metadata +218 -99
  62. data/.gemtest +0 -0
  63. data/History.rdoc +0 -54
  64. data/diff-lcs.gemspec +0 -51
  65. data/docs/artistic.html +0 -289
@@ -1,151 +1,140 @@
1
- #! /usr/env/bin ruby
2
- #--
3
- # Copyright 2004 Austin Ziegler <diff-lcs@halostatue.ca>
4
- # adapted from:
5
- # Algorithm::Diff (Perl) by Ned Konz <perl@bike-nomad.com>
6
- # Smalltalk by Mario I. Wolczko <mario@wolczko.com>
7
- # implements McIlroy-Hunt diff algorithm
8
- #
9
- # This program is free software. It may be redistributed and/or modified under
10
- # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
- # Ruby licence.
12
- #
13
- # $Id$
14
- #++
15
- # Provides Diff::LCS::Change and Diff::LCS::ContextChange.
16
-
17
- # Centralises the change test code in Diff::LCS::Change and
18
- # Diff::LCS::ContextChange, since it's the same for both classes.
19
- module Diff::LCS::ChangeTypeTests
20
- def deleting?
21
- @action == '-'
22
- end
1
+ # frozen_string_literal: true
23
2
 
24
- def adding?
25
- @action == '+'
26
- end
3
+ # Represents a simplistic (non-contextual) change. Represents the removal or
4
+ # addition of an element from either the old or the new sequenced
5
+ # enumerable.
6
+ class Diff::LCS::Change
7
+ IntClass = 1.class # Fixnum is deprecated in Ruby 2.4 # rubocop:disable Naming/ConstantName
27
8
 
28
- def unchanged?
29
- @action == '='
9
+ # The only actions valid for changes are '+' (add), '-' (delete), '='
10
+ # (no change), '!' (changed), '<' (tail changes from first sequence), or
11
+ # '>' (tail changes from second sequence). The last two ('<>') are only
12
+ # found with Diff::LCS::diff and Diff::LCS::sdiff.
13
+ VALID_ACTIONS = %w(+ - = ! > <).freeze
14
+
15
+ def self.valid_action?(action)
16
+ VALID_ACTIONS.include? action
30
17
  end
31
18
 
32
- def changed?
33
- @changed == '!'
19
+ # Returns the action this Change represents.
20
+ attr_reader :action
21
+
22
+ # Returns the position of the Change.
23
+ attr_reader :position
24
+ # Returns the sequence element of the Change.
25
+ attr_reader :element
26
+
27
+ def initialize(*args)
28
+ @action, @position, @element = *args
29
+
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 finished_a?
37
- @changed == '>'
34
+ def inspect(*_args)
35
+ "#<#{self.class}: #{to_a.inspect}>"
38
36
  end
39
37
 
40
- def finished_b?
41
- @changed == '<'
38
+ def to_a
39
+ [@action, @position, @element]
42
40
  end
43
- end
44
41
 
45
- # Represents a simplistic (non-contextual) change. Represents the removal or
46
- # addition of an element from either the old or the new sequenced enumerable.
47
- class Diff::LCS::Change
48
- # Returns the action this Change represents. Can be '+' (#adding?), '-'
49
- # (#deleting?), '=' (#unchanged?), # or '!' (#changed?). When created by
50
- # Diff::LCS#diff or Diff::LCS#sdiff, it may also be '>' (#finished_a?) or
51
- # '<' (#finished_b?).
52
- attr_reader :action
53
- attr_reader :position
54
- attr_reader :element
42
+ alias to_ary to_a
43
+
44
+ def self.from_a(arr)
45
+ arr = arr.flatten(1)
46
+ case arr.size
47
+ when 5
48
+ Diff::LCS::ContextChange.new(*(arr[0...5]))
49
+ when 3
50
+ Diff::LCS::Change.new(*(arr[0...3]))
51
+ else
52
+ fail 'Invalid change array format provided.'
53
+ end
54
+ end
55
55
 
56
56
  include Comparable
57
+
57
58
  def ==(other)
58
- (self.action == other.action) and
59
- (self.position == other.position) and
60
- (self.element == other.element)
59
+ (self.class == other.class) and
60
+ (action == other.action) and
61
+ (position == other.position) and
62
+ (element == other.element)
61
63
  end
62
64
 
63
65
  def <=>(other)
64
- r = self.action <=> other.action
65
- r = self.position <=> other.position if r.zero?
66
- 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?
67
69
  r
68
70
  end
69
71
 
70
- def initialize(action, position, element)
71
- @action = action
72
- @position = position
73
- @element = element
72
+ def adding?
73
+ @action == '+'
74
74
  end
75
75
 
76
- # Creates a Change from an array produced by Change#to_a.
77
- def to_a
78
- [@action, @position, @element]
76
+ def deleting?
77
+ @action == '-'
79
78
  end
80
79
 
81
- def self.from_a(arr)
82
- Diff::LCS::Change.new(arr[0], arr[1], arr[2])
80
+ def unchanged?
81
+ @action == '='
83
82
  end
84
83
 
85
- include Diff::LCS::ChangeTypeTests
84
+ def changed?
85
+ @action == '!'
86
+ end
87
+
88
+ def finished_a?
89
+ @action == '>'
90
+ end
91
+
92
+ def finished_b?
93
+ @action == '<'
94
+ end
86
95
  end
87
96
 
88
- # Represents a contextual change. Contains the position and values of the
89
- # elements in the old and the new sequenced enumerables as well as the action
90
- # taken.
91
- class Diff::LCS::ContextChange
92
- # Returns the action this Change represents. Can be '+' (#adding?), '-'
93
- # (#deleting?), '=' (#unchanged?), # or '!' (#changed?). When
94
- # created by Diff::LCS#diff or Diff::LCS#sdiff, it may also be '>'
95
- # (#finished_a?) or '<' (#finished_b?).
96
- attr_reader :action
97
+ # Represents a contextual change. Contains the position and values of the
98
+ # elements in the old and the new sequenced enumerables as well as the action
99
+ # taken.
100
+ class Diff::LCS::ContextChange < Diff::LCS::Change
101
+ # We don't need these two values.
102
+ undef :position
103
+ undef :element
104
+
105
+ # Returns the old position being changed.
97
106
  attr_reader :old_position
98
- attr_reader :old_element
107
+ # Returns the new position being changed.
99
108
  attr_reader :new_position
109
+ # Returns the old element being changed.
110
+ attr_reader :old_element
111
+ # Returns the new element being changed.
100
112
  attr_reader :new_element
101
113
 
102
- include Comparable
103
-
104
- def ==(other)
105
- (@action == other.action) and
106
- (@old_position == other.old_position) and
107
- (@new_position == other.new_position) and
108
- (@old_element == other.old_element) and
109
- (@new_element == other.new_element)
110
- end
114
+ def initialize(*args)
115
+ @action, @old_position, @old_element, @new_position, @new_element = *args
111
116
 
112
- def inspect(*args)
113
- %Q(#<#{self.class.name}:#{__id__} @action=#{action} positions=#{old_position},#{new_position} elements=#{old_element.inspect},#{new_element.inspect}>)
114
- end
115
-
116
- def <=>(other)
117
- r = @action <=> other.action
118
- r = @old_position <=> other.old_position if r.zero?
119
- r = @new_position <=> other.new_position if r.zero?
120
- r = @old_element <=> other.old_element if r.zero?
121
- r = @new_element <=> other.new_element if r.zero?
122
- r
123
- end
124
-
125
- def initialize(action, old_position, old_element, new_position, new_element)
126
- @action = action
127
- @old_position = old_position
128
- @old_element = old_element
129
- @new_position = new_position
130
- @new_element = new_element
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
131
120
  end
132
121
 
133
122
  def to_a
134
- [@action, [@old_position, @old_element], [@new_position, @new_element]]
123
+ [
124
+ @action,
125
+ [@old_position, @old_element],
126
+ [@new_position, @new_element]
127
+ ]
135
128
  end
136
129
 
137
- # Creates a ContextChange from an array produced by ContextChange#to_a.
130
+ alias to_ary to_a
131
+
138
132
  def self.from_a(arr)
139
- if arr.size == 5
140
- Diff::LCS::ContextChange.new(arr[0], arr[1], arr[2], arr[3], arr[4])
141
- else
142
- Diff::LCS::ContextChange.new(arr[0], arr[1][0], arr[1][1], arr[2][0],
143
- arr[2][1])
144
- end
133
+ Diff::LCS::Change.from_a(arr)
145
134
  end
146
135
 
147
- # Simplifies a context change for use in some diff callbacks. '<' actions
148
- # are converted to '-' and '>' actions are converted to '+'.
136
+ # Simplifies a context change for use in some diff callbacks. '<' actions
137
+ # are converted to '-' and '>' actions are converted to '+'.
149
138
  def self.simplify(event)
150
139
  ea = event.to_a
151
140
 
@@ -165,5 +154,21 @@ class Diff::LCS::ContextChange
165
154
  Diff::LCS::ContextChange.from_a(ea)
166
155
  end
167
156
 
168
- include Diff::LCS::ChangeTypeTests
157
+ def ==(other)
158
+ (self.class == other.class) and
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)
164
+ end
165
+
166
+ def <=>(other)
167
+ r = @action <=> other.action
168
+ r = @old_position <=> other.old_position if r.zero?
169
+ r = @new_position <=> other.new_position if r.zero?
170
+ r = @old_element <=> other.old_element if r.zero?
171
+ r = @new_element <=> other.new_element if r.zero?
172
+ r
173
+ end
169
174
  end
@@ -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 = left.map { |line| formatter.expand(line.chomp) }
119
- @right = 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>
@@ -147,5 +148,3 @@ h1 { margin-left: 2em; }
147
148
  OUTPUT
148
149
  end
149
150
  end
150
-
151
- # vim: ft=ruby