require "rubygems/requirement" ## # The Dependency class holds a Gem name and a Gem::Requirement. class Gem::Dependency # :stopdoc: @warned_version_requirement = false def self.warned_version_requirement @warned_version_requirement end def self.warned_version_requirement= value @warned_version_requirement = value end # :startdoc: ## # Valid dependency types. #-- # When this list is updated, be sure to change # Gem::Specification::CURRENT_SPECIFICATION_VERSION as well. TYPES = [ :development, :runtime, ] ## # Dependency name or regular expression. attr_accessor :name ## # Allows you to force this dependency to be a prerelease. attr_writer :prerelease ## # Dependency type. attr_reader :type ## # Constructs a dependency with +name+ and +requirements+. The last # argument can optionally be the dependency type, which defaults to # :runtime. def initialize name, *requirements type = Symbol === requirements.last ? requirements.pop : :runtime requirements = requirements.first if 1 == requirements.length # unpack unless TYPES.include? type raise ArgumentError, "Valid types are #{TYPES.inspect}, " + "not #{@type.inspect}" end @name = name @requirement = Gem::Requirement.create requirements @type = type @prerelease = false # This is for Marshal backwards compatability. See the comments in # +requirement+ for the dirty details. @version_requirements = @requirement end ## # A dependency's hash is the XOR of the hashes of +name+, +type+, # and +requirement+. def hash # :nodoc: name.hash ^ type.hash ^ requirement.hash end def inspect # :nodoc: "<%s type=%p name=%p requirements=%p>" % [self.class, @type, @name, requirement.to_s] end ## # Does this dependency require a prerelease? def prerelease? @prerelease || requirement.prerelease? end def pretty_print(q) # :nodoc: q.group 1, 'Gem::Dependency.new(', ')' do q.pp name q.text ',' q.breakable q.pp requirement q.text ',' q.breakable q.pp type end end ## # What does this dependency require? def requirement return @requirement if defined?(@requirement) and @requirement # @version_requirements and @version_requirement are legacy ivar # names, and supported here because older gems need to keep # working and Dependency doesn't implement marshal_dump and # marshal_load. In a happier world, this would be an # attr_accessor. The horrifying instance_variable_get you see # below is also the legacy of some old restructurings. # # Note also that because of backwards compatibility (loading new # gems in an old RubyGems installation), we can't add explicit # marshaling to this class until we want to make a big # break. Maybe 2.0. # # Children, define explicit marshal and unmarshal behavior for # public classes. Marshal formats are part of your public API. if defined?(@version_requirement) && @version_requirement version = @version_requirement.instance_variable_get :@version @version_requirement = nil @version_requirements = Gem::Requirement.new version end @requirement = @version_requirements if defined?(@version_requirements) end ## # Rails subclasses Gem::Dependency and uses this method, so we'll hack # around it. alias __requirement requirement # :nodoc: def requirements_list requirement.as_list end def to_s # :nodoc: "#{name} (#{requirement}, #{type})" end def version_requirements # :nodoc: unless Gem::Dependency.warned_version_requirement then warn "#{Gem.location_of_caller.join ':'}:Warning: " \ "Gem::Dependency#version_requirements is deprecated " \ "and will be removed on or after August 2010. " \ "Use #requirement" Gem::Dependency.warned_version_requirement = true end __requirement end alias version_requirement version_requirements # :nodoc: def version_requirements= requirements # :nodoc: warn "#{Gem.location_of_caller.join ':'}:Warning: " \ "Gem::Dependency#version_requirements= is deprecated " \ "and will be removed on or after August 2010. " \ "Use Gem::Dependency.new." @requirement = Gem::Requirement.create requirements end def == other # :nodoc: Gem::Dependency === other && self.name == other.name && self.type == other.type && self.requirement == other.requirement end ## # Dependencies are ordered by name. def <=> other [@name] <=> [other.name] end ## # Uses this dependency as a pattern to compare to +other+. This # dependency will match if the name matches the other's name, and # other has only an equal version requirement that satisfies this # dependency. def =~ other unless Gem::Dependency === other other = Gem::Dependency.new other.name, other.version rescue return false end pattern = name if Regexp === pattern then return false unless pattern =~ other.name else return false unless pattern == other.name end reqs = other.requirement.requirements return false unless reqs.length == 1 return false unless reqs.first.first == '=' version = reqs.first.last requirement.satisfied_by? version end def match?(spec_name, spec_version) pattern = name if Regexp === pattern return false unless pattern =~ spec_name else return false unless pattern == spec_name end return true if requirement.none? requirement.satisfied_by? Gem::Version.new(spec_version) end end