Class: Pod::YAMLHelper
- Inherits:
-
Object
- Object
- Pod::YAMLHelper
- Defined in:
- lib/cocoapods-core/yaml_helper.rb
Overview
Remove any code required solely for Ruby 1.8.x.
This class misses important features necessary for a correct YAML serialization and thus it is safe to use only for the Lockfile. The missing features include:
- Strings are never quoted even when ambiguous.
Converts objects to their YAML representation.
This class was created for the need having control on how the YAML is representation is generated. In details it provides:
- sorting for hashes in ruby 1.8.x
- ability to hint the sorting of the keys of a dictionary when converting it. In this case the keys are also separated by an additional new line feed for readability.
Array Sorting collapse
- RESOLVED_TAGS =
Regexp.union( 'null', 'Null', 'NULL', '~', '', # resolve to null 'true', 'True', 'TRUE', 'false', 'False', 'FALSE', # bool 'yes', 'Yes', 'YES', 'no', 'No', 'NO', # yes/no 'on', 'On', 'ON', 'off', 'Off', 'OFF', # no/off Regexp.new(%{ [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] # (ymd) |[0-9][0-9][0-9][0-9] # (year) -[0-9][0-9]? # (month) -[0-9][0-9]? # (day) ([Tt]|[ \t]+)[0-9][0-9]? # (hour) :[0-9][0-9] # (minute) :[0-9][0-9] # (second) (\.[0-9]*)? # (fraction) (([ \t]*)(Z|[-+][0-9][0-9]?(:[0-9][0-9])?))? # (time zone) }, Regexp::EXTENDED), # https://yaml.org/type/timestamp.html /[-+]?[0-9]+/, # base 10 int /00[0-7]+/, # base 8 int /0x[0-9a-fA-F]+/, # base 16 int /[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?/, # float /[-+]?\.(inf|Inf|INF)/, # infinity /\.(nan|NaN|NAN)/ # NaN )
- INDICATOR_START_CHARS =
%w(- ? : , [ ] { } # & * ! | > ' " % @ `).freeze
- INDICATOR_START =
/\A#{Regexp.union(INDICATOR_START_CHARS)}/.freeze
- RESOLVED_TAGS_PATTERN =
/\A#{Regexp.union(RESOLVED_TAGS)}\z/.freeze
- VALID_PLAIN_SCALAR_STRING =
%r{\A [\w&&[^#{INDICATOR_START_CHARS}]] # valid first character [\w/\ \(\)~<>=\.:`,-]* # all characters allowed after the first one \z}ox.freeze
Private Helpers collapse
-
.process_according_to_class(value, hash_keys_hint = nil) ⇒ String
private
The YAML representation of the given object.
-
.process_array(array) ⇒ String
private
Converts an array to YAML after sorting it.
-
.process_hash(hash, hash_keys_hint = nil, line_separator = "\n") ⇒ String
private
Converts a hash to YAML after sorting its keys.
-
.yaml_has_merge_error?(yaml_string) ⇒ Boolean
private
Check for merge errors in a YAML string.
-
.yaml_merge_conflict_msg(yaml, path = nil) ⇒ String
private
Error message describing that a merge conflict was found while parsing the YAML.
-
.yaml_parsing_error_msg(yaml, path = nil) ⇒ String
private
Error message describing a general error took happened while parsing the YAML.
Array Sorting collapse
- .process_string(string) ⇒ Object private
-
.sorted_array(array) ⇒ Array
Sorts an array according to the string representation of it values.
-
.sorted_array_with_hint(array, sort_hint) ⇒ Array
private
Sorts an array using another one as a sort hint.
-
.sorting_string(value) ⇒ String
private
Returns the string representation of a value useful for sorting.
Class Method Summary collapse
-
.convert(value) ⇒ String
Returns the YAML representation of the given object.
- .convert_hash(value, hash_keys_hint, line_separator = "\n") ⇒ Object
-
.load_file(file_path) ⇒ Hash, Array
Loads a YAML file and leans on the #load_string imp to do error detection.
-
.load_string(yaml_string, file_path = nil) ⇒ Hash, Array
Loads a YAML string and provide more informative error messages in special cases like merge conflict.
Class Method Details
.convert(value) ⇒ String
Returns the YAML representation of the given object. If the given object is a Hash, it accepts an optional hint for sorting the keys.
35 36 37 38 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 35 def convert(value) result = process_according_to_class(value) result << "\n" end |
.convert_hash(value, hash_keys_hint, line_separator = "\n") ⇒ Object
40 41 42 43 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 40 def convert_hash(value, hash_keys_hint, line_separator = "\n") result = process_hash(value, hash_keys_hint, line_separator) result << "\n" end |
.load_file(file_path) ⇒ Hash, Array
Loads a YAML file and leans on the #load_string imp to do error detection
74 75 76 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 74 def load_file(file_path) load_string(File.read(file_path), file_path) end |
.load_string(yaml_string, file_path = nil) ⇒ Hash, Array
Loads a YAML string and provide more informative error messages in special cases like merge conflict.
56 57 58 59 60 61 62 63 64 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 56 def load_string(yaml_string, file_path = nil) YAML.safe_load(yaml_string, :permitted_classes => [Date, Time, Symbol]) rescue if yaml_has_merge_error?(yaml_string) raise Informative, yaml_merge_conflict_msg(yaml_string, file_path) else raise Informative, yaml_parsing_error_msg(yaml_string, file_path) end end |
.process_according_to_class(value, hash_keys_hint = nil) ⇒ String (private)
Returns the YAML representation of the given object.
95 96 97 98 99 100 101 102 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 95 def process_according_to_class(value, hash_keys_hint = nil) case value when Array then process_array(value) when Hash then process_hash(value, hash_keys_hint) when String then process_string(value) else YAML.dump(value, :line_width => 2**31 - 1).sub(/\A---/, '').sub(/[.]{3}\s*\Z/, '') end.strip end |
.process_array(array) ⇒ String (private)
Converts an array to YAML after sorting it.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 111 def process_array(array) return '[]' if array.empty? result = sorted_array(array).map do |array_value| processed = process_according_to_class(array_value) case array_value when Array, Hash if array_value.size > 1 processed = processed.gsub(/^.*/).to_a head = processed.shift processed.map { |s| " #{s}" }.prepend(head).join("\n") else processed end else processed end end "- #{result.join("\n- ").strip}" end |
.process_hash(hash, hash_keys_hint = nil, line_separator = "\n") ⇒ String (private)
If a hint for sorting the keys is provided the array is assumed to be the root object and the keys are separated by an additional new line feed for readability.
If the value of a given key is a String it displayed inline, otherwise it is displayed below and indented.
Converts a hash to YAML after sorting its keys. Optionally accepts a hint for sorting the keys.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 147 def process_hash(hash, hash_keys_hint = nil, line_separator = "\n") return '{}' if hash.empty? keys = sorted_array_with_hint(hash.keys, hash_keys_hint) key_lines = keys.map do |key| key_value = hash[key] processed = process_according_to_class(key_value) processed_key = process_according_to_class(key) case key_value when Hash, Array key_partial_yaml = processed.lines.map { |line| " #{line}" } * '' "#{processed_key}:\n#{key_partial_yaml}" else "#{processed_key}: #{processed}" end end key_lines * line_separator end |
.process_string(string) ⇒ Object (private)
320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 320 def process_string(string) case string when RESOLVED_TAGS_PATTERN "'#{string}'" when /\A\s*\z/, INDICATOR_START, /:\z/ string.inspect when VALID_PLAIN_SCALAR_STRING string else string.inspect end end |
.sorted_array(array) ⇒ Array
This stuff is here only because the Lockfile intermixes strings
and hashes for the PODS
key. The Lockfile should be more
consistent.
If the value contained in the array is another Array or a Hash the first value of the collection is used for sorting, as this method is more useful, for arrays which contains a collection composed by one object.
Sorts an array according to the string representation of it values. This method allows to sort arrays which contains strings or hashes.
256 257 258 259 260 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 256 def sorted_array(array) array.each_with_index.sort_by do |element, index| [sorting_string(element), index] end.map(&:first) end |
.sorted_array_with_hint(array, sort_hint) ⇒ Array (private)
Sorts an array using another one as a sort hint. All the values of the hint which appear in the array will be returned respecting the order in the hint. If any other key is present in the original array they are sorted using the #sorted_array method.
230 231 232 233 234 235 236 237 238 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 230 def sorted_array_with_hint(array, sort_hint) if sort_hint hinted = sort_hint & array remaining = array - sort_hint hinted + sorted_array(remaining) else sorted_array(array) end end |
.sorting_string(value) ⇒ String (private)
Returns the string representation of a value useful for sorting.
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 271 def sorting_string(value) return '' unless value case value when String then value.downcase when Symbol then sorting_string(value.to_s) when Array then sorting_string(value.first) when Hash then value.keys.map { |key| key.to_s.downcase }.sort.first else raise ArgumentError, "Cannot sort #{value.inspect}" end end |
.yaml_has_merge_error?(yaml_string) ⇒ Boolean (private)
Check for merge errors in a YAML string.
173 174 175 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 173 def yaml_has_merge_error?(yaml_string) yaml_string.include?('<<<<<<< HEAD') end |
.yaml_merge_conflict_msg(yaml, path = nil) ⇒ String (private)
Error message describing that a merge conflict was found while parsing the YAML.
188 189 190 191 192 193 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 188 def yaml_merge_conflict_msg(yaml, path = nil) err = 'ERROR: Parsing unable to continue due ' err += "to merge conflicts present in:\n" err += "the file located at #{path}\n" if path err + "#{yaml}" end |
.yaml_parsing_error_msg(yaml, path = nil) ⇒ String (private)
Error message describing a general error took happened while parsing the YAML.
206 207 208 209 210 211 |
# File 'lib/cocoapods-core/yaml_helper.rb', line 206 def yaml_parsing_error_msg(yaml, path = nil) err = 'ERROR: Parsing unable to continue due ' err += "to parsing error:\n" err += "contained in the file located at #{path}\n" if path err + "#{yaml}" end |