Class: Gem::YAMLSerializer::Builder
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/rubygems/yaml_serializer.rb |
Constant Summary
-
ARRAY_FIELDS =
# File 'lib/rubygems/yaml_serializer.rb', line 383%w[rdoc_options files test_files executables requirements extra_rdoc_files].freeze
-
VALID_OPS =
# File 'lib/rubygems/yaml_serializer.rb', line 382%w[= != > < >= <= ~>].freeze
Class Method Summary
Instance Method Summary
- #build(node)
- #build_dependency(node) private
- #build_hash(node) private
- #build_mapping(node) private
- #build_node(node) private
- #build_platform(node) private
- #build_requirement(node) private
- #build_safe_requirement(req_value) private
- #build_specification(hash) private
- #build_version(node) private
- #check_anchor!(node) private
- #normalize_array_field(value) private
- #normalize_array_fields!(hash) private
- #normalize_rdoc_options!(hash) private
- #normalize_specification_version!(hash) private
- #pairs_to_hash(node) private
- #resolve_alias(node) private
- #store_anchor(name, value) private
- #validate_symbol!(sym) private
- #validate_tag!(tag) private
Constructor Details
.new(permitted_classes: [], permitted_symbols: [], aliases: true) ⇒ Builder
# File 'lib/rubygems/yaml_serializer.rb', line 385
def initialize(permitted_classes: [], permitted_symbols: [], aliases: true) @permitted_tags = Array(permitted_classes).map do |c| "!ruby/object:#{c.is_a?(Module) ? c.name : c}" end @permitted_symbols = permitted_symbols @aliases = aliases @anchor_values = {} end
Instance Method Details
#build(node)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 394
def build(node) return {} if node.nil? result = build_node(node) if result.is_a?(Hash) && (result[:tag] == "!ruby/object:Gem::Specification" || result["tag"] == "!ruby/object:Gem::Specification") build_specification(result) else result end end
#build_dependency(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 514
def build_dependency(node) hash = pairs_to_hash(node) d = Gem::Dependency.allocate d.instance_variable_set(:@name, hash["name"]) requirement = build_safe_requirement(hash["requirement"]) d.instance_variable_set(:@requirement, requirement) type = hash["type"] type = type ? type.to_s.sub(/^:/, "").to_sym : :runtime validate_symbol!(type) d.instance_variable_set(:@type, type) d.instance_variable_set(:@prerelease, ["true", true].include?(hash["prerelease"])) d.instance_variable_set(:@version_requirements, d.instance_variable_get(:@requirement)) d end
#build_hash(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 455
def build_hash(node) result = {} node.pairs.each do |key_node, value_node| key = key_node.is_a?(Scalar) ? key_node.value.to_s : build_node(key_node).to_s value = build_node(value_node) if ARRAY_FIELDS.include?(key) value = normalize_array_field(value) end result[key] = value end result end
#build_mapping(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 431
def build_mapping(node) validate_tag!(node.tag) if node.tag check_anchor!(node) result = case node.tag when "!ruby/object:Gem::Version" build_version(node) when "!ruby/object:Gem::Platform" build_platform(node) when "!ruby/object:Gem::Requirement", "!ruby/object:Gem::Version::Requirement" build_requirement(node) when "!ruby/object:Gem::Dependency" build_dependency(node) when nil build_hash(node) else hash = build_hash(node) hash[:tag] = node.tag hash end store_anchor(node.anchor, result) end
#build_node(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 410
def build_node(node) case node when nil then nil when AliasRef then resolve_alias(node) when Scalar then store_anchor(node.anchor, node.value) when Mapping then build_mapping(node) when Sequence then store_anchor(node.anchor, node.items.map {|item| build_node(item) }) else node # already a Ruby object end end
#build_platform(node) (private)
[ GitHub ]#build_requirement(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 484
def build_requirement(node) r = Gem::Requirement.allocate hash = pairs_to_hash(node) reqs = hash["requirements"] || hash["value"] reqs = [] unless reqs.is_a?(Array) if reqs.is_a?(Array) && !reqs.empty? safe_reqs = [] reqs.each do |item| if item.is_a?(Array) && item.size == 2 op = item[0].to_s ver = item[1] if VALID_OPS.include?(op) version_obj = ver.is_a?(Gem::Version) ? ver : Gem::Version.new(ver.to_s) safe_reqs << [op, version_obj] end elsif item.is_a?(String) parsed = Gem::Requirement.parse(item) safe_reqs << parsed end rescue Gem::Requirement::BadRequirementError, Gem::Version::BadVersionError # Skip malformed items silently end reqs = safe_reqs unless safe_reqs.empty? end r.instance_variable_set(:@requirements, reqs) r end
#build_safe_requirement(req_value) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 552
def build_safe_requirement(req_value) return Gem::Requirement.default unless req_value converted = req_value return Gem::Requirement.default unless converted.is_a?(Gem::Requirement) reqs = converted.instance_variable_get(:@requirements) if reqs&.is_a?(Array) valid = reqs.all? do |item| next true if item == Gem::Requirement::DefaultRequirement item.is_a?(Array) && item.size >= 2 && VALID_OPS.include?(item[0].to_s) end valid ? converted : Gem::Requirement.default else converted end rescue StandardError Gem::Requirement.default end
#build_specification(hash) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 532
def build_specification(hash) spec = Gem::Specification.allocate normalize_specification_version!(hash) (hash) normalize_array_fields!(hash) spec.yaml_initialize("!ruby/object:Gem::Specification", hash) spec end
#build_version(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 470
def build_version(node) hash = pairs_to_hash(node) Gem::Version.new((hash["version"] || hash["value"]).to_s) end
#check_anchor!(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 592
def check_anchor!(node) if node.anchor raise Psych::AliasesNotEnabled unless @aliases end end
#normalize_array_field(value) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 628
def normalize_array_field(value) if value.is_a?(Hash) value.values.flatten.compact elsif !value.is_a?(Array) && value [value].flatten.compact else value end end
#normalize_array_fields!(hash) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 621
def normalize_array_fields!(hash) ARRAY_FIELDS.each do |field| next if field == "rdoc_options" # already handled hash[field] = normalize_array_field(hash[field]) if hash[field] end end
#normalize_rdoc_options!(hash) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 604
def (hash) opts = hash["rdoc_options"] if opts.is_a?(Hash) hash["rdoc_options"] = opts.values.flatten.compact.map(&:to_s) elsif opts.is_a?(Array) hash["rdoc_options"] = opts.flat_map do |opt| if opt.is_a?(Hash) opt.flat_map {|k, v| [k.to_s, v.to_s] } elsif opt.is_a?(String) opt else opt.to_s end end end end
#normalize_specification_version!(hash) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 598
def normalize_specification_version!(hash) val = hash["specification_version"] return unless val && !val.is_a?(Integer) hash["specification_version"] = val.to_i if val.is_a?(String) && /\A\d+\z/.match?(val) end
#pairs_to_hash(node) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 543
def pairs_to_hash(node) result = {} node.pairs.each do |key_node, value_node| key = key_node.is_a?(Scalar) ? key_node.value.to_s : build_node(key_node).to_s result[key] = build_node(value_node) end result end
#resolve_alias(node) (private)
# File 'lib/rubygems/yaml_serializer.rb', line 421
def resolve_alias(node) raise Psych::AliasesNotEnabled unless @aliases @anchor_values.fetch(node.name, nil) end
#store_anchor(name, value) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 426
def store_anchor(name, value) @anchor_values[name] = value if name value end
#validate_symbol!(sym) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 582
def validate_symbol!(sym) if @permitted_symbols.any? && !@permitted_symbols.include?(sym.to_s) if defined?(Psych::VERSION) raise Psych::DisallowedClass.new("load", sym.inspect) else raise Psych::DisallowedClass, "Tried to load unspecified class: #{sym.inspect}" end end end
#validate_tag!(tag) (private)
[ GitHub ]# File 'lib/rubygems/yaml_serializer.rb', line 572
def validate_tag!(tag) unless @permitted_tags.include?(tag) if defined?(Psych::VERSION) raise Psych::DisallowedClass.new("load", tag) else raise Psych::DisallowedClass, "Tried to load unspecified class: #{tag}" end end end