C0 code coverage information
Generated on Wed Oct 07 08:34:05 -0700 2009 with rcov 0.8.2.1
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with this
3 # work for additional information regarding copyright ownership. The ASF
4 # licenses this file to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations under
14 # the License.
15
16
17 module Buildr
18
19 #
20 # See ArtifactNamespace#need
21 class VersionRequirement
22
23 CMP_PROCS = Gem::Requirement::OPS.dup
24 CMP_REGEX = Gem::Requirement::OP_RE.dup
25 CMP_CHARS = CMP_PROCS.keys.join
26 BOOL_CHARS = '\|\&\!'
27 VER_CHARS = '\w\.\-'
28
29 class << self
30 # is +str+ a version string?
31 def version?(str)
32 /^\s*[#{VER_CHARS}]+\s*$/ === str
33 end
34
35 # is +str+ a version requirement?
36 def requirement?(str)
37 /[#{BOOL_CHARS}#{CMP_CHARS}\(\)]/ === str
38 end
39
40 # :call-seq:
41 # VersionRequirement.create(" >1 <2 !(1.5) ") -> requirement
42 #
43 # parse the +str+ requirement
44 def create(str)
45 instance_eval normalize(str)
46 rescue StandardError => e
47 raise "Failed to parse #{str.inspect} due to: #{e}"
48 end
49
50 private
51 def requirement(req)
52 unless req =~ /^\s*(#{CMP_REGEX})?\s*([#{VER_CHARS}]+)\s*$/
53 raise "Invalid requirement string: #{req}"
54 end
55 comparator, version = $1, $2
56 version = Gem::Version.new(0).tap { |v| v.version = version }
57 VersionRequirement.new(nil, [$1, version])
58 end
59
60 def negate(vreq)
61 vreq.negative = !vreq.negative
62 vreq
63 end
64
65 def normalize(str)
66 str = str.strip
67 if str[/[^\s\(\)#{BOOL_CHARS + VER_CHARS + CMP_CHARS}]/]
68 raise "version string #{str.inspect} contains invalid characters"
69 end
70 str.gsub!(/\s+(and|\&\&)\s+/, ' & ')
71 str.gsub!(/\s+(or|\|\|)\s+/, ' | ')
72 str.gsub!(/(^|\s*)not\s+/, ' ! ')
73 pattern = /(#{CMP_REGEX})?\s*[#{VER_CHARS}]+/
74 left_pattern = /[#{VER_CHARS}\)]$/
75 right_pattern = /^(#{pattern}|\()/
76 str = str.split.inject([]) do |ary, i|
77 ary << '&' if ary.last =~ left_pattern && i =~ right_pattern
78 ary << i
79 end
80 str = str.join(' ')
81 str.gsub!(/!([^=])?/, ' negate \1')
82 str.gsub!(pattern) do |expr|
83 case expr.strip
84 when 'not', 'negate' then 'negate '
85 else 'requirement("' + expr + '")'
86 end
87 end
88 str.gsub!(/negate\s+\(/, 'negate(')
89 str
90 end
91 end
92
93 def initialize(op, *requirements) #:nodoc:
94 @op, @requirements = op, requirements
95 end
96
97 # Is this object a composed requirement?
98 # VersionRequirement.create('1').composed? -> false
99 # VersionRequirement.create('1 | 2').composed? -> true
100 # VersionRequirement.create('1 & 2').composed? -> true
101 def composed?
102 requirements.size > 1
103 end
104
105 # Return the last requirement on this object having an = operator.
106 def default
107 default = nil
108 requirements.reverse.find do |r|
109 if Array === r
110 if !negative && (r.first.nil? || r.first.include?('='))
111 default = r.last.to_s
112 end
113 else
114 default = r.default
115 end
116 end
117 default
118 end
119
120 # Test if this requirement can be satisfied by +version+
121 def satisfied_by?(version)
122 return false unless version
123 unless version.kind_of?(Gem::Version)
124 raise "Invalid version: #{version.inspect}" unless self.class.version?(version)
125 version = Gem::Version.new(0).tap { |v| v.version = version.strip }
126 end
127 message = op == :| ? :any? : :all?
128 result = requirements.send message do |req|
129 if Array === req
130 cmp, rv = *req
131 CMP_PROCS[cmp || '='].call(version, rv)
132 else
133 req.satisfied_by?(version)
134 end
135 end
136 negative ? !result : result
137 end
138
139 # Either modify the current requirement (if it's already an or operation)
140 # or create a new requirement
141 def |(other)
142 operation(:|, other)
143 end
144
145 # Either modify the current requirement (if it's already an and operation)
146 # or create a new requirement
147 def &(other)
148 operation(:&, other)
149 end
150
151 # return the parsed expression
152 def to_s
153 str = requirements.map(&:to_s).join(" " + @op.to_s + " ").to_s
154 str = "( " + str + " )" if negative || requirements.size > 1
155 str = "!" + str if negative
156 str
157 end
158
159 attr_accessor :negative
160 protected
161 attr_reader :requirements, :op
162 def operation(op, other)
163 @op ||= op
164 if negative == other.negative && @op == op && other.requirements.size == 1
165 @requirements << other.requirements.first
166 self
167 else
168 self.class.new(op, self, other)
169 end
170 end
171 end # VersionRequirement
172 end
Generated using the rcov code coverage analysis tool for Ruby
version 0.8.2.1.