ruby/lib/rubygems/specification.rb
##
# Checks that the specification contains all required fields, and does a
# very basic sanity check.
#
# Raises InvalidSpecificationException if the spec does not pass the
# checks..
Checks that the specification contains all required fields, and does a
very basic sanity check.

Raises InvalidSpecificationException if the spec does not pass the
checks
Checks that the specification contains all required fields and does a very basic sanity check . Raises InvalidSpecificationException if the spec does not pass the checks
def validate packaging = true
    @warnings = 0
    require 'rubygems/user_interaction'
    extend Gem::UserInteraction
    normalize
    nil_attributes = self.class.non_nil_attributes.find_all do |attrname|
      instance_variable_get("@#{attrname}").nil?
    end
    unless nil_attributes.empty? then
      raise Gem::InvalidSpecificationException,
        "#{nil_attributes.join ', '} must not be nil"
    end
    if packaging and rubygems_version != Gem::VERSION then
      raise Gem::InvalidSpecificationException,
            "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
    end
    @@required_attributes.each do |symbol|
      unless self.send symbol then
        raise Gem::InvalidSpecificationException,
              "missing value for attribute #{symbol}"
      end
    end
    unless String === name then
      raise Gem::InvalidSpecificationException,
            "invalid value for attribute name: \"#{name.inspect}\""
    end
    if raw_require_paths.empty? then
      raise Gem::InvalidSpecificationException,
            'specification must have at least one require_path'
    end
    @files.delete_if            { |x| File.directory?(x) && !File.symlink?(x) }
    @test_files.delete_if       { |x| File.directory?(x) && !File.symlink?(x) }
    @executables.delete_if      { |x| File.directory?(File.join(@bindir, x)) }
    @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
    @extensions.delete_if       { |x| File.directory?(x) && !File.symlink?(x) }
    non_files = files.reject { |x| File.file?(x) || File.symlink?(x) }
    unless not packaging or non_files.empty? then
      raise Gem::InvalidSpecificationException,
            "[\"#{non_files.join "\", \""}\"] are not files"
    end
    if files.include? file_name then
      raise Gem::InvalidSpecificationException,
            "#{full_name} contains itself (#{file_name}), check your files list"
    end
    unless specification_version.is_a?(Integer)
      raise Gem::InvalidSpecificationException,
            'specification_version must be an Integer (did you mean version?)'
    end
    case platform
    when Gem::Platform, Gem::Platform::RUBY then 
    else
      raise Gem::InvalidSpecificationException,
            "invalid platform #{platform.inspect}, see Gem::Platform"
    end
    self.class.array_attributes.each do |field|
      val = self.send field
      klass = case field
              when :dependencies
                Gem::Dependency
              else
                String
              end
      unless Array === val and val.all? { |x| x.kind_of?(klass) } then
        raise(Gem::InvalidSpecificationException,
              "#{field} must be an Array of #{klass}")
      end
    end
    [:authors].each do |field|
      val = self.send field
      raise Gem::InvalidSpecificationException, "#{field} may not be empty" if
        val.empty?
    end
    unless Hash === metadata
      raise Gem::InvalidSpecificationException,
              'metadata must be a hash'
    end
    metadata.keys.each do |k|
      if !k.kind_of?(String)
        raise Gem::InvalidSpecificationException,
                'metadata keys must be a String'
      end
      if k.size > 128
        raise Gem::InvalidSpecificationException,
                "metadata key too large (#{k.size} > 128)"
      end
    end
    metadata.values.each do |k|
      if !k.kind_of?(String)
        raise Gem::InvalidSpecificationException,
                'metadata values must be a String'
      end
      if k.size > 1024
        raise Gem::InvalidSpecificationException,
                "metadata value too large (#{k.size} > 1024)"
      end
    end
    licenses.each { |license|
      if license.length > 64
        raise Gem::InvalidSpecificationException,
          "each license must be 64 characters or less"
      end
      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
    }
    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
    validate_permissions
    lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
    unless authors.grep(/FI XME|TO DO/x).empty? then
      raise Gem::InvalidSpecificationException, "#{lazy} is not an author"
    end
    unless Array(email).grep(/FI XME|TO DO/x).empty? then
      raise Gem::InvalidSpecificationException, "#{lazy} is not an email"
    end
    if description =~ /FI XME|TO DO/x then
      raise Gem::InvalidSpecificationException, "#{lazy} is not a description"
    end
    if summary =~ /FI XME|TO DO/x then
      raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
    end
    if homepage and not homepage.empty? and
       homepage !~ /\A[a-z][a-z\d+.-]*:/i then
      raise Gem::InvalidSpecificationException,
            "\"#{homepage}\" is not a URI"
    end
    %w[author email homepage summary].each do |attribute|
      value = self.send attribute
      warning "no #{attribute} specified" if value.nil? or value.empty?
    end
    if description == summary then
      warning 'description and summary are identical'
    end
    warning "deprecated autorequire specified" if autorequire
    executables.each do |executable|
      executable_path = File.join(bindir, executable)
      shebang = File.read(executable_path, 2) == '#!'
      warning "#{executable_path} is missing #! line" unless shebang
    end
    files.each do |file|
      next unless File.symlink?(file)
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
    validate_dependencies
    true
  ensure
    if $! or @warnings > 0 then
      alert_warning "See http://guides.rubygems.org/specification-reference/ for help"
    end
  end
def validate packaging = true @warnings = 0 require 'rubygems/user_interaction' extend Gem :: UserInteraction normalize nil_attributes = self . class . non_nil_attributes . find_all do | attrname | instance_variable_get ( "@#{attrname}" ) . nil? end unless nil_attributes . empty? then raise Gem :: InvalidSpecificationException , "#{nil_attributes.join ', '} must not be nil" end if packaging and rubygems_version != Gem :: VERSION then raise Gem :: InvalidSpecificationException , "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" end @@required_attributes . each do | symbol | unless self . send symbol then raise Gem :: InvalidSpecificationException , "missing value for attribute #{symbol}" end end unless String === name then raise Gem :: InvalidSpecificationException , "invalid value for attribute name: \"#{name.inspect}\"" end if raw_require_paths . empty? then raise Gem :: InvalidSpecificationException , 'specification must have at least one require_path' end @files . delete_if { | x | File . directory? ( x ) && ! File . symlink? ( x ) } @test_files . delete_if { | x | File . directory? ( x ) && ! File . symlink? ( x ) } @executables . delete_if { | x | File . directory? ( File . join ( @bindir , x ) ) } @extra_rdoc_files . delete_if { | x | File . directory? ( x ) && ! File . symlink? ( x ) } @extensions . delete_if { | x | File . directory? ( x ) && ! File . symlink? ( x ) } non_files = files . reject { | x | File . file? ( x ) || File . symlink? ( x ) } unless not packaging or non_files . empty? then raise Gem :: InvalidSpecificationException , "[\"#{non_files.join "\", \""}\"] are not files" end if files . include? file_name then raise Gem :: InvalidSpecificationException , "#{full_name} contains itself (#{file_name}), check your files list" end unless specification_version . is_a? ( Integer ) raise Gem :: InvalidSpecificationException , 'specification_version must be an Integer (did you mean version?)' end case platform when Gem :: Platform , Gem :: Platform :: RUBY then else raise Gem :: InvalidSpecificationException , "invalid platform #{platform.inspect}, see Gem::Platform" end self . class . array_attributes . each do | field | val = self . send field klass = case field when :dependencies Gem :: Dependency else String end unless Array === val and val . all? { | x | x . kind_of? ( klass ) } then raise ( Gem :: InvalidSpecificationException , "#{field} must be an Array of #{klass}" ) end end [ :authors ] . each do | field | val = self . send field raise Gem :: InvalidSpecificationException , "#{field} may not be empty" if val . empty? end unless Hash === metadata raise Gem :: InvalidSpecificationException , 'metadata must be a hash' end metadata . keys . each do | k | if ! k . kind_of? ( String ) raise Gem :: InvalidSpecificationException , 'metadata keys must be a String' end if k . size > 128 raise Gem :: InvalidSpecificationException , "metadata key too large (#{k.size} > 128)" end end metadata . values . each do | k | if ! k . kind_of? ( String ) raise Gem :: InvalidSpecificationException , 'metadata values must be a String' end if k . size > 1024 raise Gem :: InvalidSpecificationException , "metadata value too large (#{k.size} > 1024)" end end licenses . each { | license | if license . length > 64 raise Gem :: InvalidSpecificationException , "each license must be 64 characters or less" end 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 } 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 validate_permissions lazy = '"FIxxxXME" or "TOxxxDO"' . gsub ( / xxx / , '' ) unless authors . grep ( / FI XME|TO DO /x ) . empty? then raise Gem :: InvalidSpecificationException , "#{lazy} is not an author" end unless Array ( email ) . grep ( / FI XME|TO DO /x ) . empty? then raise Gem :: InvalidSpecificationException , "#{lazy} is not an email" end if description =~ / FI XME|TO DO /x then raise Gem :: InvalidSpecificationException , "#{lazy} is not a description" end if summary =~ / FI XME|TO DO /x then raise Gem :: InvalidSpecificationException , "#{lazy} is not a summary" end if homepage and not homepage . empty? and homepage !~ / \A [a-z][a-z \d +.-]*: /i then raise Gem :: InvalidSpecificationException , "\"#{homepage}\" is not a URI" end %w[ author email homepage summary ] . each do | attribute | value = self . send attribute warning "no #{attribute} specified" if value . nil? or value . empty? end if description == summary then warning 'description and summary are identical' end warning "deprecated autorequire specified" if autorequire executables . each do | executable | executable_path = File . join ( bindir , executable ) shebang = File . read ( executable_path , 2 ) == '#!' warning "#{executable_path} is missing #! line" unless shebang end files . each do | file | next unless File . symlink? ( file ) warning "#{file} is a symlink, which is not supported on all platforms" end validate_dependencies true ensure if $! or @warnings > 0 then alert_warning "See http://guides.rubygems.org/specification-reference/ for help" end end
Checks that the specification contains all required fields, and does a
very basic sanity check.
Checks that the specification contains all required fields and does a very basic sanity check .
# ok # reject lazy developers: # Warnings # TODO: raise at some given date
packaging
<not_specific>