/usr/lib/ruby/vendor_ruby/rspec/support/differ.rb is in ruby-rspec-support 3.5.0c3e0m0s0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | RSpec::Support.require_rspec_support 'encoded_string'
RSpec::Support.require_rspec_support 'hunk_generator'
RSpec::Support.require_rspec_support "object_formatter"
require 'pp'
module RSpec
module Support
# rubocop:disable ClassLength
class Differ
def diff(actual, expected)
diff = ""
if actual && expected
if all_strings?(actual, expected)
if any_multiline_strings?(actual, expected)
diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected))
end
elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
diff = diff_as_object(actual, expected)
end
end
diff.to_s
end
# rubocop:disable MethodLength
def diff_as_string(actual, expected)
encoding = EncodedString.pick_encoding(actual, expected)
actual = EncodedString.new(actual, encoding)
expected = EncodedString.new(expected, encoding)
output = EncodedString.new("\n", encoding)
hunks = build_hunks(actual, expected)
hunks.each_cons(2) do |prev_hunk, current_hunk|
begin
if current_hunk.overlaps?(prev_hunk)
add_old_hunk_to_hunk(current_hunk, prev_hunk)
else
add_to_output(output, prev_hunk.diff(format_type).to_s)
end
ensure
add_to_output(output, "\n")
end
end
finalize_output(output, hunks.last.diff(format_type).to_s) if hunks.last
color_diff output
rescue Encoding::CompatibilityError
handle_encoding_errors(actual, expected)
end
# rubocop:enable MethodLength
def diff_as_object(actual, expected)
actual_as_string = object_to_string(actual)
expected_as_string = object_to_string(expected)
diff_as_string(actual_as_string, expected_as_string)
end
def color?
@color
end
def initialize(opts={})
@color = opts.fetch(:color, false)
@object_preparer = opts.fetch(:object_preparer, lambda { |string| string })
end
private
def no_procs?(*args)
safely_flatten(args).none? { |a| Proc === a }
end
def all_strings?(*args)
safely_flatten(args).all? { |a| String === a }
end
def any_multiline_strings?(*args)
all_strings?(*args) && safely_flatten(args).any? { |a| multiline?(a) }
end
def no_numbers?(*args)
safely_flatten(args).none? { |a| Numeric === a }
end
def coerce_to_string(string_or_array)
return string_or_array unless Array === string_or_array
diffably_stringify(string_or_array).join("\n")
end
def diffably_stringify(array)
array.map do |entry|
if Array === entry
entry.inspect
else
entry.to_s.gsub("\n", "\\n")
end
end
end
if String.method_defined?(:encoding)
def multiline?(string)
string.include?("\n".encode(string.encoding))
end
else
def multiline?(string)
string.include?("\n")
end
end
def build_hunks(actual, expected)
HunkGenerator.new(actual, expected).hunks
end
def finalize_output(output, final_line)
add_to_output(output, final_line)
add_to_output(output, "\n")
end
def add_to_output(output, string)
output << string
end
def add_old_hunk_to_hunk(hunk, oldhunk)
hunk.merge(oldhunk)
end
def safely_flatten(array)
array = array.flatten(1) until (array == array.flatten(1))
array
end
def format_type
:unified
end
def color(text, color_code)
"\e[#{color_code}m#{text}\e[0m"
end
def red(text)
color(text, 31)
end
def green(text)
color(text, 32)
end
def blue(text)
color(text, 34)
end
def normal(text)
color(text, 0)
end
def color_diff(diff)
return diff unless color?
diff.lines.map do |line|
case line[0].chr
when "+"
green line
when "-"
red line
when "@"
line[1].chr == "@" ? blue(line) : normal(line)
else
normal(line)
end
end.join
end
def object_to_string(object)
object = @object_preparer.call(object)
case object
when Hash
hash_to_string(object)
when Array
PP.pp(ObjectFormatter.prepare_for_inspection(object), "")
when String
object =~ /\n/ ? object : object.inspect
else
PP.pp(object, "")
end
end
def hash_to_string(hash)
formatted_hash = ObjectFormatter.prepare_for_inspection(hash)
formatted_hash.keys.sort_by { |k| k.to_s }.map do |key|
pp_key = PP.singleline_pp(key, "")
pp_value = PP.singleline_pp(formatted_hash[key], "")
"#{pp_key} => #{pp_value},"
end.join("\n")
end
def handle_encoding_errors(actual, expected)
if actual.source_encoding != expected.source_encoding
"Could not produce a diff because the encoding of the actual string " \
"(#{actual.source_encoding}) differs from the encoding of the expected " \
"string (#{expected.source_encoding})"
else
"Could not produce a diff because of the encoding of the string " \
"(#{expected.source_encoding})"
end
end
end
# rubocop:enable ClassLength
end
end
|