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
Calls superclass method Delegator.new
# File lib/rubygems/specification_policy.rb, line 21
def initialize(specification)
  @warnings = 0

  super(specification)
end

Public Instance Methods

validate(strict = false) click to toggle source

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.

# File lib/rubygems/specification_policy.rb, line 39
def validate(strict = false)
  validate_nil_attributes

  validate_rubygems_version

  validate_required_attributes

  validate_name

  validate_require_paths

  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

  validate_permissions

  validate_lazy_metadata

  validate_values

  validate_dependencies

  if @warnings > 0
    if strict
      error "specification has warnings"
    else
      alert_warning help_text
    end
  end

  true
end
validate_array_attribute(field) click to toggle source
# File lib/rubygems/specification_policy.rb, line 281
def validate_array_attribute(field)
  val = self.send(field)
  klass = case field
          when :dependencies then
            Gem::Dependency
          else
            String
          end

  unless Array === val and val.all? {|x| x.kind_of?(klass)}
    raise(Gem::InvalidSpecificationException,
          "#{field} must be an Array of #{klass}")
  end
end
validate_array_attributes() click to toggle source
# File lib/rubygems/specification_policy.rb, line 275
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 380
def validate_attribute_present(attribute)
  value = self.send attribute
  warning("no #{attribute} specified") if value.nil? || value.empty?
end
validate_authors_field() click to toggle source
# File lib/rubygems/specification_policy.rb, line 296
  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def help_text # :nodoc:
    "See http://guides.rubygems.org/specification-reference/ for help"
  end
validate_lazy_metadata() click to toggle source
# File lib/rubygems/specification_policy.rb, line 329
def validate_lazy_metadata
  unless authors.grep(LAZY_PATTERN).empty?
    error "#{LAZY} is not an author"
  end

  unless Array(email).grep(LAZY_PATTERN).empty?
    error "#{LAZY} is not an email"
  end

  if description =~ LAZY_PATTERN
    error "#{LAZY} is not a description"
  end

  if summary =~ LAZY_PATTERN
    error "#{LAZY} is not a summary"
  end

  # Make sure a homepage is valid HTTP/HTTPS URI
  if homepage and not homepage.empty?
    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 302
  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end
validate_metadata() click to toggle source

Implementation for Specification#validate_metadata

# File lib/rubygems/specification_policy.rb, line 90
def validate_metadata
  unless Hash === metadata
    error 'metadata must be a hash'
  end

  metadata.each do |key, value|
    if !key.kind_of?(String)
      error "metadata keys must be a String"
    end

    if key.size > 128
      error "metadata key too large (#{key.size} > 128)"
    end

    if !value.kind_of?(String)
      error "metadata values must be a String"
    end

    if value.size > 1024
      error "metadata value too large (#{value.size} > 1024)"
    end

    if METADATA_LINK_KEYS.include? key
      if value !~ VALID_URI_PATTERN
        error "metadata['#{key}'] has invalid link: #{value.inspect}"
      end
    end
  end
end
validate_name() click to toggle source
# File lib/rubygems/specification_policy.rb, line 228
def validate_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 205
  def validate_nil_attributes
    nil_attributes = Gem::Specification.non_nil_attributes.select do |attrname|
      __getobj__.instance_variable_get("@#{attrname}").nil?
    end
    return if nil_attributes.empty?
    error "#{nil_attributes.join ', '} must not be nil"
  end

  def validate_rubygems_version
    return unless packaging
    return if rubygems_version == Gem::VERSION

    error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
  end

  def validate_required_attributes
    Gem::Specification.required_attributes.each do |symbol|
      unless send symbol
        error "missing value for attribute #{symbol}"
      end
    end
  end

  def validate_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

  def validate_require_paths
    return unless raw_require_paths.empty?

    error 'specification must have at least one require_path'
  end

  def validate_non_files
    return unless packaging
    non_files = files.reject {|x| File.file?(x) || File.symlink?(x)}

    unless non_files.empty?
      error "[\"#{non_files.join "\", \""}\"] are not files"
    end
  end

  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end
validate_non_files() click to toggle source
# File lib/rubygems/specification_policy.rb, line 246
  def validate_non_files
    return unless packaging
    non_files = files.reject {|x| File.file?(x) || File.symlink?(x)}

    unless non_files.empty?
      error "[\"#{non_files.join "\", \""}\"] are not files"
    end
  end

  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def help_text 
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 186
  def validate_permissions
    return if Gem.win_platform?

    files.each do |file|
      next unless File.file?(file)
      next if File.stat(file).mode & 0444 == 0444
      warning "#{file} is not world-readable"
    end

    executables.each do |name|
      exec = File.join bindir, name
      next unless File.file?(exec)
      next if File.stat(exec).executable?
      warning "#{exec} is not executable"
    end
  end

  private

  def validate_nil_attributes
    nil_attributes = Gem::Specification.non_nil_attributes.select do |attrname|
      __getobj__.instance_variable_get("@#{attrname}").nil?
    end
    return if nil_attributes.empty?
    error "#{nil_attributes.join ', '} must not be nil"
  end

  def validate_rubygems_version
    return unless packaging
    return if rubygems_version == Gem::VERSION

    error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
  end

  def validate_required_attributes
    Gem::Specification.required_attributes.each do |symbol|
      unless send symbol
        error "missing value for attribute #{symbol}"
      end
    end
  end

  def validate_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

  def validate_require_paths
    return unless raw_require_paths.empty?

    error 'specification must have at least one require_path'
  end

  def validate_non_files
    return unless packaging
    non_files = files.reject {|x| File.file?(x) || File.symlink?(x)}

    unless non_files.empty?
      error "[\"#{non_files.join "\", \""}\"] are not files"
    end
  end

  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  
validate_platform() click to toggle source
# File lib/rubygems/specification_policy.rb, line 267
def validate_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 240
  def validate_require_paths
    return unless raw_require_paths.empty?

    error 'specification must have at least one require_path'
  end

  def validate_non_files
    return unless packaging
    non_files = files.reject {|x| File.file?(x) || File.symlink?(x)}

    unless non_files.empty?
      error "[\"#{non_files.join "\", \""}\"] are not files"
    end
  end

  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def 
validate_required_attributes() click to toggle source
# File lib/rubygems/specification_policy.rb, line 220
def validate_required_attributes
  Gem::Specification.required_attributes.each do |symbol|
    unless 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 213
  def validate_rubygems_version
    return unless packaging
    return if rubygems_version == Gem::VERSION

    error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
  end

  def validate_required_attributes
    Gem::Specification.required_attributes.each do |symbol|
      unless send symbol
        error "missing value for attribute #{symbol}"
      end
    end
  end

  def validate_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

  def validate_require_paths
    return unless raw_require_paths.empty?

    error 'specification must have at least one require_path'
  end

  def validate_non_files
    return unless packaging
    non_files = files.reject {|x| File.file?(x) || File.symlink?(x)}

    unless non_files.empty?
      error "[\"#{non_files.join "\", \""}\"] are not files"
    end
  end

  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  
validate_self_inclusion_in_files_list() click to toggle source
# File lib/rubygems/specification_policy.rb, line 255
  def validate_self_inclusion_in_files_list
    return unless files.include?(file_name)

    error "#{full_name} contains itself (#{file_name}), check your files list"
  end

  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def help_text # :nodoc:
    
validate_shebang_line_in(executable) click to toggle source
# File lib/rubygems/specification_policy.rb, line 385
  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def help_text # :nodoc:
    "See http://guides.rubygems.org/specification-reference/ for help"
  end
end
validate_specification_version() click to toggle source
# File lib/rubygems/specification_policy.rb, line 261
  def validate_specification_version
    return if specification_version.is_a?(Integer)

    error 'specification_version must be an Integer (did you mean version?)'
  end

  def validate_platform
    case platform
    when Gem::Platform, Gem::Platform::RUBY  # ok
    else
      error "invalid platform #{platform.inspect}, see Gem::Platform"
    end
  end

  def validate_array_attributes
    Gem::Specification.array_attributes.each do |field|
      validate_array_attribute(field)
    end
  end

  def validate_array_attribute(field)
    val = self.send(field)
    klass = case field
            when :dependencies then
              Gem::Dependency
            else
              String
            end

    unless Array === val and val.all? {|x| x.kind_of?(klass)}
      raise(Gem::InvalidSpecificationException,
            "#{field} must be an Array of #{klass}")
    end
  end

  def validate_authors_field
    return unless authors.empty?

    error "authors may not be empty"
  end

  def validate_licenses
    licenses.each { |license|
      if license.length > 64
        error "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
  end

  LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  LAZY_PATTERN = /FI XME|TO DO/x.freeze
  HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze

  def validate_lazy_metadata
    unless authors.grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an author"
    end

    unless Array(email).grep(LAZY_PATTERN).empty?
      error "#{LAZY} is not an email"
    end

    if description =~ LAZY_PATTERN
      error "#{LAZY} is not a description"
    end

    if summary =~ LAZY_PATTERN
      error "#{LAZY} is not a summary"
    end

    # Make sure a homepage is valid HTTP/HTTPS URI
    if homepage and not homepage.empty?
      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

  def validate_values
    %w[author homepage summary files].each do |attribute|
      validate_attribute_present(attribute)
    end

    if description == summary
      warning "description and summary are identical"
    end

    # TODO: raise at some given date
    warning "deprecated autorequire specified" if autorequire

    executables.each do |executable|
      validate_shebang_line_in(executable)
    end

    files.select { |f| File.symlink?(f) }.each do |file|
      warning "#{file} is a symlink, which is not supported on all platforms"
    end
  end

  def validate_attribute_present(attribute)
    value = self.send attribute
    warning("no #{attribute} specified") if value.nil? || value.empty?
  end

  def validate_shebang_line_in(executable)
    executable_path = File.join(bindir, executable)
    return if File.read(executable_path, 2) == '#!'

    warning "#{executable_path} is missing #! line"
  end

  def warning(statement) # :nodoc:
    @warnings += 1

    alert_warning statement
  end

  def error(statement) # :nodoc:
    raise Gem::InvalidSpecificationException, statement
  ensure
    alert_warning help_text
  end

  def help_text # :nodoc:
    "See http://guides.rubygems.org/specification-reference/ for help"
validate_values() click to toggle source
# File lib/rubygems/specification_policy.rb, line 359
def validate_values
  %w[author homepage summary files].each do |attribute|
    validate_attribute_present(attribute)
  end

  if description == summary
    warning "description and summary are identical"
  end

  # TODO: raise at some given date
  warning "deprecated autorequire specified" if autorequire

  executables.each do |executable|
    validate_shebang_line_in(executable)
  end

  files.select { |f| File.symlink?(f) }.each do |file|
    warning "#{file} is a symlink, which is not supported on all platforms"
  end
end