diff-lcs 1.6.2 → 2.0.0.beta.2

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +65 -4
  3. data/CONTRIBUTING.md +91 -35
  4. data/CONTRIBUTORS.md +19 -9
  5. data/LICENCE.md +39 -11
  6. data/Manifest.txt +91 -83
  7. data/README.md +13 -9
  8. data/Rakefile +99 -73
  9. data/SECURITY.md +22 -27
  10. data/integration/compare/array_diff_spec.rb +10 -0
  11. data/integration/compare/hash_diff_spec.rb +25 -0
  12. data/integration/compare/string_diff_spec.rb +10 -0
  13. data/integration/rspec_differ_spec.rb +26 -0
  14. data/integration/rspec_expectations_spec.rb +32 -0
  15. data/integration/runner +20 -0
  16. data/lib/diff/lcs/block.rb +29 -24
  17. data/lib/diff/lcs/callbacks.rb +240 -242
  18. data/lib/diff/lcs/change.rb +102 -104
  19. data/lib/diff/lcs/hunk.rb +92 -155
  20. data/lib/diff/lcs/internals.rb +92 -96
  21. data/lib/diff/lcs/ldiff.rb +30 -38
  22. data/lib/diff/lcs/version.rb +1 -1
  23. data/lib/diff/lcs.rb +439 -466
  24. data/licenses/dco.txt +34 -0
  25. data/spec/hunk_spec.rb +32 -45
  26. data/spec/lcs_spec.rb +6 -6
  27. data/spec/ldiff_spec.rb +8 -8
  28. data/spec/spec_helper.rb +17 -27
  29. data/test/fixtures/ldiff/output.diff-c +7 -0
  30. data/test/fixtures/ldiff/output.diff-u +5 -0
  31. data/test/fixtures/ldiff/output.diff.bin2 +1 -0
  32. data/test/fixtures/ldiff/output.diff.bin2-c +1 -0
  33. data/test/fixtures/ldiff/output.diff.bin2-e +1 -0
  34. data/test/fixtures/ldiff/output.diff.bin2-f +1 -0
  35. data/test/fixtures/ldiff/output.diff.bin2-u +1 -0
  36. data/{spec → test}/fixtures/ldiff/output.diff.chef-c +2 -2
  37. data/test/fixtures/ldiff/output.diff.chef-u +9 -0
  38. data/{spec → test}/fixtures/ldiff/output.diff.chef2-c +2 -2
  39. data/{spec → test}/fixtures/ldiff/output.diff.chef2-u +2 -2
  40. data/test/fixtures/ldiff/output.diff.empty.vs.four_lines-c +9 -0
  41. data/test/fixtures/ldiff/output.diff.empty.vs.four_lines-u +7 -0
  42. data/test/fixtures/ldiff/output.diff.four_lines.vs.empty-c +9 -0
  43. data/test/fixtures/ldiff/output.diff.four_lines.vs.empty-u +7 -0
  44. data/test/fixtures/ldiff/output.diff.issue95_trailing_context-c +9 -0
  45. data/test/fixtures/ldiff/output.diff.issue95_trailing_context-u +6 -0
  46. data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-c +2 -2
  47. data/test/fixtures/ldiff/output.diff.missing_new_line1-u +9 -0
  48. data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-c +2 -2
  49. data/test/fixtures/ldiff/output.diff.missing_new_line2-u +9 -0
  50. data/test/test_block.rb +34 -0
  51. data/test/test_change.rb +234 -0
  52. data/test/test_diff.rb +53 -0
  53. data/test/test_helper.rb +225 -0
  54. data/test/test_hunk.rb +72 -0
  55. data/test/test_issues.rb +168 -0
  56. data/test/test_lcs.rb +47 -0
  57. data/test/test_ldiff.rb +89 -0
  58. data/test/test_patch.rb +362 -0
  59. data/test/test_sdiff.rb +167 -0
  60. data/test/test_traverse_balanced.rb +322 -0
  61. data/test/test_traverse_sequences.rb +187 -0
  62. metadata +199 -110
  63. data/.rspec +0 -1
  64. data/bin/htmldiff +0 -35
  65. data/lib/diff/lcs/backports.rb +0 -13
  66. data/lib/diff/lcs/htmldiff.rb +0 -160
  67. data/mise.toml +0 -5
  68. data/spec/fixtures/ldiff/output.diff-c +0 -7
  69. data/spec/fixtures/ldiff/output.diff-e +0 -3
  70. data/spec/fixtures/ldiff/output.diff-f +0 -3
  71. data/spec/fixtures/ldiff/output.diff-u +0 -5
  72. data/spec/fixtures/ldiff/output.diff.bin2 +0 -1
  73. data/spec/fixtures/ldiff/output.diff.bin2-c +0 -1
  74. data/spec/fixtures/ldiff/output.diff.bin2-e +0 -1
  75. data/spec/fixtures/ldiff/output.diff.bin2-f +0 -1
  76. data/spec/fixtures/ldiff/output.diff.bin2-u +0 -1
  77. data/spec/fixtures/ldiff/output.diff.chef-e +0 -3
  78. data/spec/fixtures/ldiff/output.diff.chef-f +0 -3
  79. data/spec/fixtures/ldiff/output.diff.chef-u +0 -9
  80. data/spec/fixtures/ldiff/output.diff.chef2-e +0 -7
  81. data/spec/fixtures/ldiff/output.diff.chef2-f +0 -7
  82. data/spec/fixtures/ldiff/output.diff.empty.vs.four_lines-c +0 -9
  83. data/spec/fixtures/ldiff/output.diff.empty.vs.four_lines-u +0 -7
  84. data/spec/fixtures/ldiff/output.diff.four_lines.vs.empty-c +0 -9
  85. data/spec/fixtures/ldiff/output.diff.four_lines.vs.empty-u +0 -7
  86. data/spec/fixtures/ldiff/output.diff.issue95_trailing_context-c +0 -9
  87. data/spec/fixtures/ldiff/output.diff.issue95_trailing_context-u +0 -6
  88. data/spec/fixtures/ldiff/output.diff.missing_new_line1-u +0 -9
  89. data/spec/fixtures/ldiff/output.diff.missing_new_line2-u +0 -9
  90. /data/{docs → licenses}/COPYING.txt +0 -0
  91. /data/{docs → licenses}/artistic.txt +0 -0
  92. /data/{spec → test}/fixtures/123_x +0 -0
  93. /data/{spec → test}/fixtures/456_x +0 -0
  94. /data/{spec → test}/fixtures/aX +0 -0
  95. /data/{spec → test}/fixtures/bXaX +0 -0
  96. /data/{spec → test}/fixtures/ds1.csv +0 -0
  97. /data/{spec → test}/fixtures/ds2.csv +0 -0
  98. /data/{spec → test}/fixtures/empty +0 -0
  99. /data/{spec → test}/fixtures/file1.bin +0 -0
  100. /data/{spec → test}/fixtures/file2.bin +0 -0
  101. /data/{spec → test}/fixtures/four_lines +0 -0
  102. /data/{spec → test}/fixtures/four_lines_with_missing_new_line +0 -0
  103. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line1-e +0 -0
  104. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line1-f +0 -0
  105. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line2-e +0 -0
  106. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line2-f +0 -0
  107. /data/{spec → test}/fixtures/ldiff/error.diff.chef-e +0 -0
  108. /data/{spec → test}/fixtures/ldiff/error.diff.chef-f +0 -0
  109. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line1-e +0 -0
  110. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line1-f +0 -0
  111. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line2-e +0 -0
  112. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line2-f +0 -0
  113. /data/{spec → test}/fixtures/ldiff/output.diff +0 -0
  114. /data/{spec → test}/fixtures/ldiff/output.diff.bin1 +0 -0
  115. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-c +0 -0
  116. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-e +0 -0
  117. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-f +0 -0
  118. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-u +0 -0
  119. /data/{spec → test}/fixtures/ldiff/output.diff.chef +0 -0
  120. /data/{spec → test}/fixtures/ldiff/output.diff.chef2 +0 -0
  121. /data/{spec → test}/fixtures/ldiff/output.diff.chef2-d +0 -0
  122. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines +0 -0
  123. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines-e +0 -0
  124. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines-f +0 -0
  125. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty +0 -0
  126. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty-e +0 -0
  127. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty-f +0 -0
  128. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context +0 -0
  129. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context-e +0 -0
  130. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context-f +0 -0
  131. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1 +0 -0
  132. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-e +0 -0
  133. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-f +0 -0
  134. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2 +0 -0
  135. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-e +0 -0
  136. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-f +0 -0
  137. /data/{spec → test}/fixtures/new-chef +0 -0
  138. /data/{spec → test}/fixtures/new-chef2 +0 -0
  139. /data/{spec → test}/fixtures/old-chef +0 -0
  140. /data/{spec → test}/fixtures/old-chef2 +0 -0
@@ -1,53 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
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 # standard:disable Naming/ConstantName
3
+ Diff::LCS::Change = Data.define(:action, :position, :element) # :nodoc:
4
+ Diff::LCS::ContextChange = Data.define(:action, :old_position, :old_element, :new_position, :new_element) # :nodoc:
8
5
 
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
6
+ # Represents a simplistic (non-contextual) change. Represents the removal or addition of
7
+ # an element from either the old or the new sequenced enumerable.
8
+ class Diff::LCS::Change
9
+ # The only actions valid for changes are '+' (add), '-' (delete), '=' (no change), '!'
10
+ # (changed), '<' (tail changes from first sequence), or '>' (tail changes from second
11
+ # sequence). The last two ('<>') are only found with Diff::LCS::diff and
12
+ # Diff::LCS::sdiff.
13
+ VALID_ACTIONS = %w[= - + ! > <].freeze
14
14
 
15
- def self.valid_action?(action)
16
- VALID_ACTIONS.include? action
17
- end
15
+ def self.valid_action?(action) = VALID_ACTIONS.include?(action)
18
16
 
17
+ ##
19
18
  # Returns the action this Change represents.
20
- attr_reader :action
19
+ # :attr_reader: action
21
20
 
21
+ ##
22
22
  # Returns the position of the Change.
23
- attr_reader :position
23
+ # :attr_reader: position
24
+
25
+ ##
24
26
  # Returns the sequence element of the Change.
25
- attr_reader :element
27
+ # :attr_reader: element
26
28
 
27
- def initialize(*args)
28
- @action, @position, @element = *args
29
+ def initialize(action:, position:, element:)
30
+ fail "Invalid Change Action '#{action}'" unless Diff::LCS::Change.valid_action?(action)
31
+ fail "Invalid Position Type" unless position.is_a?(Integer)
29
32
 
30
- fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
31
- fail "Invalid Position Type" unless @position.is_a? IntClass
33
+ super
32
34
  end
33
35
 
34
- def inspect(*_args)
35
- "#<#{self.class}: #{to_a.inspect}>"
36
- end
37
-
38
- def to_a
39
- [@action, @position, @element]
40
- end
36
+ def inspect(*_args) = "#<#{self.class}: #{to_a.inspect}>"
41
37
 
38
+ def to_a = [action, position, element]
42
39
  alias_method :to_ary, :to_a
40
+ alias_method :deconstruct, :to_a
41
+
42
+ def deconstruct_keys(_) = {action:, position:, element:}
43
43
 
44
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])
45
+ case arr
46
+ in [action, [old_position, old_element], [new_position, new_element]]
47
+ Diff::LCS::ContextChange[action, old_position, old_element, new_position, new_element]
48
+ in [action, position, element]
49
+ new(action, position, element)
51
50
  else
52
51
  fail "Invalid change array format provided."
53
52
  end
@@ -63,112 +62,111 @@ class Diff::LCS::Change
63
62
  end
64
63
 
65
64
  def <=>(other)
66
- r = action <=> other.action
67
- r = position <=> other.position if r.zero?
65
+ r = position <=> other.position
66
+ r = VALID_ACTIONS.index(action) <=> VALID_ACTIONS.index(other.action) if r.zero?
68
67
  r = element <=> other.element if r.zero?
69
68
  r
70
69
  end
71
70
 
72
- def adding?
73
- @action == "+"
74
- end
71
+ def adding? = action == "+"
75
72
 
76
- def deleting?
77
- @action == "-"
78
- end
73
+ def deleting? = action == "-"
79
74
 
80
- def unchanged?
81
- @action == "="
82
- end
75
+ def unchanged? = action == "="
83
76
 
84
- def changed?
85
- @action == "!"
86
- end
77
+ def changed? = action == "!"
87
78
 
88
- def finished_a?
89
- @action == ">"
90
- end
79
+ def finished_a? = action == ">"
91
80
 
92
- def finished_b?
93
- @action == "<"
94
- end
81
+ def finished_b? = action == "<"
95
82
  end
96
83
 
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
84
+ # Represents a contextual change. Contains the position and values of the elements in the
85
+ # old and the new sequenced enumerable values as well as the action taken.
86
+ class Diff::LCS::ContextChange
87
+ ##
88
+ # Returns the action this Change represents.
89
+ # :attr_reader: action
104
90
 
91
+ ##
105
92
  # Returns the old position being changed.
106
- attr_reader :old_position
93
+ # :attr_reader: old_position
94
+
95
+ ##
107
96
  # Returns the new position being changed.
108
- attr_reader :new_position
97
+ # :attr_reader: new_position
98
+
99
+ ##
109
100
  # Returns the old element being changed.
110
- attr_reader :old_element
111
- # Returns the new element being changed.
112
- attr_reader :new_element
101
+ # :attr_reader: old_element
113
102
 
114
- def initialize(*args)
115
- @action, @old_position, @old_element, @new_position, @new_element = *args
103
+ ##
104
+ # Returns the new element being changed.
105
+ # :attr_reader: new_element
116
106
 
117
- fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action)
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
- end
107
+ def initialize(action:, old_position:, old_element:, new_position:, new_element:)
108
+ fail "Invalid Change Action '#{action}'" unless Diff::LCS::Change.valid_action?(action)
109
+ fail "Invalid (Old) Position Type" unless old_position.nil? || old_position.is_a?(Integer)
110
+ fail "Invalid (New) Position Type" unless new_position.nil? || new_position.is_a?(Integer)
121
111
 
122
- def to_a
123
- [
124
- @action,
125
- [@old_position, @old_element],
126
- [@new_position, @new_element]
127
- ]
112
+ super
128
113
  end
129
114
 
115
+ def to_a = [action, [old_position, old_element], [new_position, new_element]]
130
116
  alias_method :to_ary, :to_a
117
+ alias_method :deconstruct, :to_a
131
118
 
132
- def self.from_a(arr)
133
- Diff::LCS::Change.from_a(arr)
134
- end
119
+ def deconstruct_keys(_) = {action:, old_position:, old_element:, new_position:, new_element:}
135
120
 
136
- # Simplifies a context change for use in some diff callbacks. '<' actions
137
- # are converted to '-' and '>' actions are converted to '+'.
138
- def self.simplify(event)
139
- ea = event.to_a
121
+ def self.from_a(arr) = Diff::LCS::Change.from_a(arr)
140
122
 
141
- case ea[0]
123
+ # Simplifies a context change for use in some diff callbacks. '<' actions are converted
124
+ # to '-' and '>' actions are converted to '+'.
125
+ def self.simplify(event)
126
+ case event.action
142
127
  when "-"
143
- ea[2][1] = nil
128
+ event.with(new_element: nil)
144
129
  when "<"
145
- ea[0] = "-"
146
- ea[2][1] = nil
130
+ event.with(action: "-", new_element: nil)
147
131
  when "+"
148
- ea[1][1] = nil
132
+ event.with(old_element: nil)
149
133
  when ">"
150
- ea[0] = "+"
151
- ea[1][1] = nil
134
+ event.with(action: "+", old_element: nil)
135
+ else
136
+ event
152
137
  end
153
-
154
- Diff::LCS::ContextChange.from_a(ea)
155
138
  end
156
139
 
157
140
  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)
141
+ (self.class == other.class) &&
142
+ (action == other.action) &&
143
+ (old_position == other.old_position) &&
144
+ (new_position == other.new_position) &&
145
+ (old_element == other.old_element) &&
146
+ (new_element == other.new_element)
164
147
  end
165
148
 
166
149
  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?
150
+ r = old_position <=> other.old_position
151
+ r = new_position <=> other.new_position if r.zero?
152
+ if r.zero?
153
+ r = Diff::LCS::Change::VALID_ACTIONS.index(action) <=>
154
+ Diff::LCS::Change::VALID_ACTIONS.index(other.action)
155
+ end
156
+ r = old_element <=> other.old_element if r.zero?
157
+ r = new_element <=> other.new_element if r.zero?
172
158
  r
173
159
  end
160
+
161
+ def adding? = action == "+"
162
+
163
+ def deleting? = action == "-"
164
+
165
+ def unchanged? = action == "="
166
+
167
+ def changed? = action == "!"
168
+
169
+ def finished_a? = action == ">"
170
+
171
+ def finished_b? = action == "<"
174
172
  end