Fix up Rubinius specific library specs.
[rbx.git] / lib / rubygems / requirement.rb
blobc9128b5ebc2b037a6ad13639e5407318c0729ade
1 #--
2 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3 # All rights reserved.
4 # See LICENSE.txt for permissions.
5 #++
7 require 'rubygems/version'
9 ##
10 # Requirement version includes a prefaced comparator in addition
11 # to a version number.
13 # A Requirement object can actually contain multiple, er,
14 # requirements, as in (> 1.2, < 2.0).
16 class Gem::Requirement
18   include Comparable
20   attr_reader :requirements
22   OPS = {
23     "="  =>  lambda { |v, r| v == r },
24     "!=" =>  lambda { |v, r| v != r },
25     ">"  =>  lambda { |v, r| v > r },
26     "<"  =>  lambda { |v, r| v < r },
27     ">=" =>  lambda { |v, r| v >= r },
28     "<=" =>  lambda { |v, r| v <= r },
29     "~>" =>  lambda { |v, r| v >= r && v < r.bump }
30   }
32   OP_RE = /#{OPS.keys.map{ |k| Regexp.quote k }.join '|'}/o
34   ##
35   # Factory method to create a Gem::Requirement object.  Input may be a
36   # Version, a String, or nil.  Intended to simplify client code.
37   #
38   # If the input is "weird", the default version requirement is returned.
40   def self.create(input)
41     case input
42     when Gem::Requirement then
43       input
44     when Gem::Version, Array then
45       new input
46     else
47       if input.respond_to? :to_str then
48         self.new [input.to_str]
49       else
50         self.default
51       end
52     end
53   end
55   ##
56   # A default "version requirement" can surely _only_ be '>= 0'.
57   #--
58   # This comment once said:
59   #
60   # "A default "version requirement" can surely _only_ be '> 0'."
62   def self.default
63     self.new ['>= 0']
64   end
66   ##
67   # Constructs a Requirement from +requirements+ which can be a String, a
68   # Gem::Version, or an Array of those.  See parse for details on the
69   # formatting of requirement strings.
71   def initialize(requirements)
72     @requirements = case requirements
73                     when Array then
74                       requirements.map do |requirement|
75                         parse(requirement)
76                       end
77                     else
78                       [parse(requirements)]
79                     end
80     @version = nil   # Avoid warnings.
81   end
83   ##
84   # Marshal raw requirements, rather than the full object
86   def marshal_dump # :nodoc:
87     [@requirements]
88   end
90   ##
91   # Load custom marshal format
93   def marshal_load(array) # :nodoc:
94     @requirements = array[0]
95     @version = nil
96   end
98   def to_s # :nodoc:
99     as_list.join(", ")
100   end
102   def as_list
103     normalize
104     @requirements.collect { |req|
105       "#{req[0]} #{req[1]}"
106     }
107   end
109   def normalize
110     return if not defined? @version or @version.nil?
111     @requirements = [parse(@version)]
112     @nums = nil
113     @version = nil
114     @op = nil
115   end
117   ##
118   # True if this requirement satisfied by the Gem::Version +version+.
120   def satisfied_by?(version)
121     normalize
122     @requirements.all? { |op, rv| satisfy?(op, version, rv) }
123   end
125   ##
126   # Is "+version+ +op+ +required_version+" satisfied?
128   def satisfy?(op, version, required_version)
129     OPS[op].call(version, required_version)
130   end
132   ##
133   # Parse the version requirement obj returning the operator and version.
134   #
135   # The requirement can be a String or a Gem::Version.  A String can be an
136   # operator (<, <=, =, =>, >, !=, ~>), a version number, or both, operator
137   # first.
139   def parse(obj)
140     case obj
141     when /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/o then
142       [$1, Gem::Version.new($2)]
143     when /^\s*([0-9.]+)\s*$/ then
144       ['=', Gem::Version.new($1)]
145     when /^\s*(#{OP_RE})\s*$/o then
146       [$1, Gem::Version.new('0')]
147     when Gem::Version then
148       ['=', obj]
149     else
150       fail ArgumentError, "Illformed requirement [#{obj.inspect}]"
151     end
152   end
154   def <=>(other) # :nodoc:
155     to_s <=> other.to_s
156   end
158   def hash # :nodoc:
159     to_s.hash
160   end