| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
|---|---|---|---|---|
| lib/buildr/packaging/version_requirement.rb | 192 | 135 | 43.23%
|
53.33%
|
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 # Rubygems 1.3.6 removed the 'version' accessor so monkey-patch it back to |
18 # circumvent version validation. This is needed because Gem::Version doesn't |
19 # accept version specs with dashes. |
20 unless Gem::Version.new(0).respond_to?(:version=) |
21 class Gem::Version |
22 def version=(version) |
23 @version = version.to_s |
24 @version.strip! |
25 |
26 # re-prime @segments |
27 @segments = nil |
28 segments |
29 end |
30 end |
31 end |
32 |
33 module Buildr |
34 |
35 # |
36 # See ArtifactNamespace#need |
37 class VersionRequirement |
38 |
39 CMP_PROCS = Gem::Requirement::OPS.dup |
40 CMP_REGEX = if defined?(Gem::Requirement::OP_RE) |
41 Gem::Requirement::OP_RE |
42 else |
43 Gem::Requirement::OPS.keys.map { |k| Regexp.quote k }.join "|" |
44 end |
45 CMP_CHARS = CMP_PROCS.keys.join |
46 BOOL_CHARS = '\|\&\!' |
47 VER_CHARS = '\w\.\-' |
48 |
49 class << self |
50 # is +str+ a version string? |
51 def version?(str) |
52 /^\s*\d[#{VER_CHARS}]*\s*$/ === str |
53 end |
54 |
55 # is +str+ a version requirement? |
56 def requirement?(str) |
57 /[#{BOOL_CHARS}#{CMP_CHARS}\(\)]/ === str |
58 end |
59 |
60 # :call-seq: |
61 # VersionRequirement.create(" >1 <2 !(1.5) ") -> requirement |
62 # |
63 # parse the +str+ requirement |
64 def create(str) |
65 instance_eval normalize(str) |
66 rescue StandardError => e |
67 raise "Failed to parse #{str.inspect} due to: #{e}" |
68 end |
69 |
70 private |
71 def requirement(req) |
72 unless req =~ /^\s*(#{CMP_REGEX})?\s*([#{VER_CHARS}]+)\s*$/ |
73 raise "Invalid requirement string: #{req}" |
74 end |
75 comparator, version = $1, $2 |
76 version = Gem::Version.new(0).tap { |v| v.version = version } |
77 VersionRequirement.new(nil, [$1, version]) |
78 end |
79 |
80 def negate(vreq) |
81 vreq.negative = !vreq.negative |
82 vreq |
83 end |
84 |
85 def normalize(str) |
86 str = str.strip |
87 if str[/[^\s\(\)#{BOOL_CHARS + VER_CHARS + CMP_CHARS}]/] |
88 raise "version string #{str.inspect} contains invalid characters" |
89 end |
90 str.gsub!(/\s+(and|\&\&)\s+/, ' & ') |
91 str.gsub!(/\s+(or|\|\|)\s+/, ' | ') |
92 str.gsub!(/(^|\s*)not\s+/, ' ! ') |
93 pattern = /(#{CMP_REGEX})?\s*[#{VER_CHARS}]+/ |
94 left_pattern = /[#{VER_CHARS}\)]$/ |
95 right_pattern = /^(#{pattern}|\()/ |
96 str = str.split.inject([]) do |ary, i| |
97 ary << '&' if ary.last =~ left_pattern && i =~ right_pattern |
98 ary << i |
99 end |
100 str = str.join(' ') |
101 str.gsub!(/!([^=])?/, ' negate \1') |
102 str.gsub!(pattern) do |expr| |
103 case expr.strip |
104 when 'not', 'negate' then 'negate ' |
105 else 'requirement("' + expr + '")' |
106 end |
107 end |
108 str.gsub!(/negate\s+\(/, 'negate(') |
109 str |
110 end |
111 end |
112 |
113 def initialize(op, *requirements) #:nodoc: |
114 @op, @requirements = op, requirements |
115 end |
116 |
117 # Is this object a composed requirement? |
118 # VersionRequirement.create('1').composed? -> false |
119 # VersionRequirement.create('1 | 2').composed? -> true |
120 # VersionRequirement.create('1 & 2').composed? -> true |
121 def composed? |
122 requirements.size > 1 |
123 end |
124 |
125 # Return the last requirement on this object having an = operator. |
126 def default |
127 default = nil |
128 requirements.reverse.find do |r| |
129 if Array === r |
130 if !negative && (r.first.nil? || r.first.include?('=')) |
131 default = r.last.to_s |
132 end |
133 else |
134 default = r.default |
135 end |
136 end |
137 default |
138 end |
139 |
140 # Test if this requirement can be satisfied by +version+ |
141 def satisfied_by?(version) |
142 return false unless version |
143 unless version.kind_of?(Gem::Version) |
144 raise "Invalid version: #{version.inspect}" unless self.class.version?(version) |
145 version = Gem::Version.new(0).tap { |v| v.version = version.strip } |
146 end |
147 message = op == :| ? :any? : :all? |
148 result = requirements.send message do |req| |
149 if Array === req |
150 cmp, rv = *req |
151 CMP_PROCS[cmp || '='].call(version, rv) |
152 else |
153 req.satisfied_by?(version) |
154 end |
155 end |
156 negative ? !result : result |
157 end |
158 |
159 # Either modify the current requirement (if it's already an or operation) |
160 # or create a new requirement |
161 def |(other) |
162 operation(:|, other) |
163 end |
164 |
165 # Either modify the current requirement (if it's already an and operation) |
166 # or create a new requirement |
167 def &(other) |
168 operation(:&, other) |
169 end |
170 |
171 # return the parsed expression |
172 def to_s |
173 str = requirements.map(&:to_s).join(" " + @op.to_s + " ").to_s |
174 str = "( " + str + " )" if negative || requirements.size > 1 |
175 str = "!" + str if negative |
176 str |
177 end |
178 |
179 attr_accessor :negative |
180 protected |
181 attr_reader :requirements, :op |
182 def operation(op, other) |
183 @op ||= op |
184 if negative == other.negative && @op == op && other.requirements.size == 1 |
185 @requirements << other.requirements.first |
186 self |
187 else |
188 self.class.new(op, self, other) |
189 end |
190 end |
191 end # VersionRequirement |
192 end |
Generated on 2011-07-06 23:35:38 -0700 with rcov 0.9.8