2007-11-10 02:48:56 -05:00
|
|
|
#--
|
|
|
|
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
|
|
|
# All rights reserved.
|
|
|
|
# See LICENSE.txt for permissions.
|
|
|
|
#++
|
|
|
|
|
|
|
|
require 'rubygems/version'
|
|
|
|
|
|
|
|
##
|
|
|
|
# Requirement version includes a prefaced comparator in addition
|
|
|
|
# to a version number.
|
|
|
|
#
|
|
|
|
# A Requirement object can actually contain multiple, er,
|
|
|
|
# requirements, as in (> 1.2, < 2.0).
|
|
|
|
class Gem::Requirement
|
|
|
|
|
|
|
|
include Comparable
|
|
|
|
|
2008-03-31 18:40:06 -04:00
|
|
|
attr_reader :requirements
|
|
|
|
|
2007-11-10 02:48:56 -05:00
|
|
|
OPS = {
|
|
|
|
"=" => lambda { |v, r| v == r },
|
|
|
|
"!=" => lambda { |v, r| v != r },
|
|
|
|
">" => lambda { |v, r| v > r },
|
|
|
|
"<" => lambda { |v, r| v < r },
|
|
|
|
">=" => lambda { |v, r| v >= r },
|
|
|
|
"<=" => lambda { |v, r| v <= r },
|
|
|
|
"~>" => lambda { |v, r| v >= r && v < r.bump }
|
|
|
|
}
|
|
|
|
|
|
|
|
OP_RE = /#{OPS.keys.map{ |k| Regexp.quote k }.join '|'}/o
|
|
|
|
|
|
|
|
##
|
|
|
|
# Factory method to create a Gem::Requirement object. Input may be a
|
|
|
|
# Version, a String, or nil. Intended to simplify client code.
|
|
|
|
#
|
|
|
|
# If the input is "weird", the default version requirement is returned.
|
|
|
|
#
|
|
|
|
def self.create(input)
|
|
|
|
case input
|
|
|
|
when Gem::Requirement then
|
|
|
|
input
|
|
|
|
when Gem::Version, Array then
|
|
|
|
new input
|
|
|
|
else
|
|
|
|
if input.respond_to? :to_str then
|
|
|
|
self.new [input.to_str]
|
|
|
|
else
|
|
|
|
self.default
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# A default "version requirement" can surely _only_ be '>= 0'.
|
|
|
|
#--
|
|
|
|
# This comment once said:
|
|
|
|
#
|
|
|
|
# "A default "version requirement" can surely _only_ be '> 0'."
|
|
|
|
def self.default
|
|
|
|
self.new ['>= 0']
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Constructs a Requirement from +requirements+ which can be a String, a
|
|
|
|
# Gem::Version, or an Array of those. See parse for details on the
|
|
|
|
# formatting of requirement strings.
|
|
|
|
def initialize(requirements)
|
|
|
|
@requirements = case requirements
|
|
|
|
when Array then
|
|
|
|
requirements.map do |requirement|
|
|
|
|
parse(requirement)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
[parse(requirements)]
|
|
|
|
end
|
|
|
|
@version = nil # Avoid warnings.
|
|
|
|
end
|
|
|
|
|
|
|
|
# Marshal raw requirements, rather than the full object
|
|
|
|
def marshal_dump
|
|
|
|
[@requirements]
|
|
|
|
end
|
|
|
|
|
|
|
|
# Load custom marshal format
|
|
|
|
def marshal_load(array)
|
|
|
|
@requirements = array[0]
|
|
|
|
@version = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_s # :nodoc:
|
|
|
|
as_list.join(", ")
|
|
|
|
end
|
|
|
|
|
|
|
|
def as_list
|
|
|
|
normalize
|
|
|
|
@requirements.collect { |req|
|
|
|
|
"#{req[0]} #{req[1]}"
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def normalize
|
|
|
|
return if not defined? @version or @version.nil?
|
|
|
|
@requirements = [parse(@version)]
|
|
|
|
@nums = nil
|
|
|
|
@version = nil
|
|
|
|
@op = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
2008-06-04 05:37:38 -04:00
|
|
|
# Is the requirement satisfied by +version+.
|
2007-11-10 02:48:56 -05:00
|
|
|
#
|
|
|
|
# version:: [Gem::Version] the version to compare against
|
|
|
|
# return:: [Boolean] true if this requirement is satisfied by
|
|
|
|
# the version, otherwise false
|
|
|
|
#
|
|
|
|
def satisfied_by?(version)
|
|
|
|
normalize
|
|
|
|
@requirements.all? { |op, rv| satisfy?(op, version, rv) }
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Is "version op required_version" satisfied?
|
|
|
|
#
|
|
|
|
def satisfy?(op, version, required_version)
|
|
|
|
OPS[op].call(version, required_version)
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Parse the version requirement obj returning the operator and version.
|
|
|
|
#
|
|
|
|
# The requirement can be a String or a Gem::Version. A String can be an
|
|
|
|
# operator (<, <=, =, =>, >, !=, ~>), a version number, or both, operator
|
|
|
|
# first.
|
|
|
|
def parse(obj)
|
|
|
|
case obj
|
|
|
|
when /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/o then
|
|
|
|
[$1, Gem::Version.new($2)]
|
|
|
|
when /^\s*([0-9.]+)\s*$/ then
|
|
|
|
['=', Gem::Version.new($1)]
|
|
|
|
when /^\s*(#{OP_RE})\s*$/o then
|
|
|
|
[$1, Gem::Version.new('0')]
|
|
|
|
when Gem::Version then
|
|
|
|
['=', obj]
|
|
|
|
else
|
|
|
|
fail ArgumentError, "Illformed requirement [#{obj.inspect}]"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def <=>(other)
|
|
|
|
to_s <=> other.to_s
|
|
|
|
end
|
|
|
|
|
|
|
|
def hash # :nodoc:
|
|
|
|
to_s.hash
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|