class Gem::SpecificationPolicy
Constants
- HOMEPAGE_URI_PATTERN
- LAZY
- LAZY_PATTERN
Attributes
packaging[RW]
If set to true, run packaging-specific checks, as well.
Public Class Methods
new(specification)
click to toggle source
# File lib/rubygems/specification_policy.rb, line 23 def initialize(specification) @warnings = 0 @specification = specification end
Public Instance Methods
validate(strict = false)
click to toggle source
Does a sanity check on the specification.
Raises InvalidSpecificationException if the spec does not pass the checks.
It also performs some validations that do not raise but print warning messages instead.
# File lib/rubygems/specification_policy.rb, line 43 def validate(strict = false) validate_required! validate_optional(strict) if packaging || strict true end
validate_metadata()
click to toggle source
Implementation for Specification#validate_metadata
# File lib/rubygems/specification_policy.rb, line 119 def validate_metadata metadata = @specification.metadata unless Hash === metadata error 'metadata must be a hash' end metadata.each do |key, value| entry = "metadata['#{key}']" if !key.kind_of?(String) error "metadata keys must be a String" end if key.size > 128 error "metadata key is too large (#{key.size} > 128)" end if !value.kind_of?(String) error "#{entry} value must be a String" end if value.size > 1024 error "#{entry} value is too large (#{value.size} > 1024)" end if METADATA_LINK_KEYS.include? key if value !~ VALID_URI_PATTERN error "#{entry} has invalid link: #{value.inspect}" end end end end
validate_optional(strict)
click to toggle source
# File lib/rubygems/specification_policy.rb, line 94 def validate_optional(strict) validate_licenses validate_permissions validate_values validate_dependencies validate_extensions validate_removed_attributes if @warnings > 0 if strict error "specification has warnings" else alert_warning help_text end end end
validate_permissions()
click to toggle source
Issues a warning for each file to be packaged which is world-readable.
Implementation for Specification#validate_permissions
# File lib/rubygems/specification_policy.rb, line 227 def validate_permissions return if Gem.win_platform? @specification.files.each do |file| next unless File.file?(file) next if File.stat(file).mode & 0444 == 0444 warning "#{file} is not world-readable" end @specification.executables.each do |name| exec = File.join @specification.bindir, name next unless File.file?(exec) next if File.stat(exec).executable? warning "#{exec} is not executable" end end
validate_required!()
click to toggle source
Does a sanity check on the specification.
Raises InvalidSpecificationException if the spec does not pass the checks.
Only runs checks that are considered necessary for the specification to be functional.
# File lib/rubygems/specification_policy.rb, line 60 def validate_required! validate_nil_attributes validate_rubygems_version validate_required_attributes validate_name validate_require_paths @specification.keep_only_files_and_directories validate_non_files validate_self_inclusion_in_files_list validate_specification_version validate_platform validate_array_attributes validate_authors_field validate_metadata validate_licenses_length validate_lazy_metadata validate_duplicate_dependencies end
Private Instance Methods
validate_array_attribute(field)
click to toggle source
# File lib/rubygems/specification_policy.rb, line 332 def validate_array_attribute(field) val = @specification.send(field) klass = case field when :dependencies then Gem::Dependency else String end unless Array === val and val.all? {|x| x.kind_of?(klass) } error "#{field} must be an Array of #{klass}" end end
validate_array_attributes()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 326 def validate_array_attributes Gem::Specification.array_attributes.each do |field| validate_array_attribute(field) end end
validate_attribute_present(attribute)
click to toggle source
# File lib/rubygems/specification_policy.rb, line 441 def validate_attribute_present(attribute) value = @specification.send attribute warning("no #{attribute} specified") if value.nil? || value.empty? end
validate_lazy_metadata()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 387 def validate_lazy_metadata unless @specification.authors.grep(LAZY_PATTERN).empty? error "#{LAZY} is not an author" end unless Array(@specification.email).grep(LAZY_PATTERN).empty? error "#{LAZY} is not an email" end if @specification.description =~ LAZY_PATTERN error "#{LAZY} is not a description" end if @specification.summary =~ LAZY_PATTERN error "#{LAZY} is not a summary" end homepage = @specification.homepage # Make sure a homepage is valid HTTP/HTTPS URI if homepage and not homepage.empty? require 'uri' begin homepage_uri = URI.parse(homepage) unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class error "\"#{homepage}\" is not a valid HTTP URI" end rescue URI::InvalidURIError error "\"#{homepage}\" is not a valid HTTP URI" end end end
validate_licenses()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 362 def validate_licenses licenses = @specification.licenses licenses.each do |license| if !Gem::Licenses.match?(license) suggestions = Gem::Licenses.suggestions(license) message = <<-WARNING license value '#{license}' is invalid. Use a license identifier from http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. WARNING message += "Did you mean #{suggestions.map {|s| "'#{s}'" }.join(', ')}?\n" unless suggestions.nil? warning(message) end end warning <<-WARNING if licenses.empty? licenses is empty, but is recommended. Use a license identifier from http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. WARNING end
validate_licenses_length()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 352 def validate_licenses_length licenses = @specification.licenses licenses.each do |license| if license.length > 64 error "each license must be 64 characters or less" end end end
validate_name()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 272 def validate_name name = @specification.name if !name.is_a?(String) error "invalid value for attribute name: \"#{name.inspect}\" must be a string" elsif name !~ /[a-zA-Z]/ error "invalid value for attribute name: #{name.dump} must include at least one letter" elsif name !~ VALID_NAME_PATTERN error "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores" elsif name =~ SPECIAL_CHARACTERS error "invalid value for attribute name: #{name.dump} can not begin with a period, dash, or underscore" end end
validate_nil_attributes()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 246 def validate_nil_attributes nil_attributes = Gem::Specification.non_nil_attributes.select do |attrname| @specification.instance_variable_get("@#{attrname}").nil? end return if nil_attributes.empty? error "#{nil_attributes.join ', '} must not be nil" end
validate_non_files()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 292 def validate_non_files return unless packaging non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x) } unless non_files.empty? error "[\"#{non_files.join "\", \""}\"] are not files" end end
validate_platform()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 316 def validate_platform platform = @specification.platform case platform when Gem::Platform, Gem::Platform::RUBY # ok else error "invalid platform #{platform.inspect}, see Gem::Platform" end end
validate_require_paths()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 286 def validate_require_paths return unless @specification.raw_require_paths.empty? error 'specification must have at least one require_path' end
validate_required_attributes()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 264 def validate_required_attributes Gem::Specification.required_attributes.each do |symbol| unless @specification.send symbol error "missing value for attribute #{symbol}" end end end
validate_rubygems_version()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 254 def validate_rubygems_version return unless packaging rubygems_version = @specification.rubygems_version return if rubygems_version == Gem::VERSION error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" end
validate_self_inclusion_in_files_list()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 302 def validate_self_inclusion_in_files_list file_name = @specification.file_name return unless @specification.files.include?(file_name) error "#{@specification.full_name} contains itself (#{file_name}), check your files list" end
validate_shebang_line_in(executable)
click to toggle source
# File lib/rubygems/specification_policy.rb, line 446 def validate_shebang_line_in(executable) executable_path = File.join(@specification.bindir, executable) return if File.read(executable_path, 2) == '#!' warning "#{executable_path} is missing #! line" end
validate_specification_version()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 310 def validate_specification_version return if @specification.specification_version.is_a?(Integer) error 'specification_version must be an Integer (did you mean version?)' end
validate_values()
click to toggle source
# File lib/rubygems/specification_policy.rb, line 420 def validate_values %w[author homepage summary files].each do |attribute| validate_attribute_present(attribute) end if @specification.description == @specification.summary warning "description and summary are identical" end # TODO: raise at some given date warning "deprecated autorequire specified" if @specification.autorequire @specification.executables.each do |executable| validate_shebang_line_in(executable) end @specification.files.select {|f| File.symlink?(f) }.each do |file| warning "#{file} is a symlink, which is not supported on all platforms" end end