OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library pub_semver.src.version_range; | 5 library pub_semver.src.version_range; |
6 | 6 |
7 import 'version.dart'; | 7 import 'version.dart'; |
8 import 'version_constraint.dart'; | 8 import 'version_constraint.dart'; |
9 import 'version_union.dart'; | |
9 | 10 |
10 /// Constrains versions to a fall within a given range. | 11 /// Constrains versions to a fall within a given range. |
11 /// | 12 /// |
12 /// If there is a minimum, then this only allows versions that are at that | 13 /// If there is a minimum, then this only allows versions that are at that |
13 /// minimum or greater. If there is a maximum, then only versions less than | 14 /// minimum or greater. If there is a maximum, then only versions less than |
14 /// that are allowed. In other words, this allows `>= min, < max`. | 15 /// that are allowed. In other words, this allows `>= min, < max`. |
15 class VersionRange implements VersionConstraint { | 16 class VersionRange implements VersionConstraint { |
16 /// The minimum end of the range. | 17 /// The minimum end of the range. |
17 /// | 18 /// |
18 /// If [includeMin] is `true`, this will be the minimum allowed version. | 19 /// If [includeMin] is `true`, this will be the minimum allowed version. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 !max.isPreRelease && other.isPreRelease && | 93 !max.isPreRelease && other.isPreRelease && |
93 other.major == max.major && other.minor == max.minor && | 94 other.major == max.major && other.minor == max.minor && |
94 other.patch == max.patch) { | 95 other.patch == max.patch) { |
95 return false; | 96 return false; |
96 } | 97 } |
97 } | 98 } |
98 | 99 |
99 return true; | 100 return true; |
100 } | 101 } |
101 | 102 |
103 bool allowsAll(VersionConstraint other) { | |
104 if (other.isEmpty) return true; | |
105 if (other is Version) return allows(other); | |
106 | |
107 if (other is VersionUnion) { | |
108 return other.constraints.every((constraint) => allowsAll(constraint)); | |
109 } | |
110 | |
111 if (other is VersionRange) { | |
112 if (min != null) { | |
113 if (other.min == null) return false; | |
114 if (min > other.min) return false; | |
115 if (min == other.min && !includeMin && other.includeMin) return false; | |
116 } | |
117 | |
118 if (max != null) { | |
119 if (other.max == null) return false; | |
120 if (max < other.max) return false; | |
121 if (max == other.max && !includeMax && other.includeMax) return false; | |
122 } | |
123 | |
124 return true; | |
125 } | |
126 | |
127 throw new ArgumentError('Unknown VersionConstraint type $other.'); | |
128 } | |
129 | |
130 bool allowsAny(VersionConstraint other) { | |
131 if (other.isEmpty) return false; | |
132 if (other is Version) return allows(other); | |
133 | |
134 if (other is VersionUnion) { | |
135 return other.constraints.any((constraint) => allowsAny(constraint)); | |
136 } | |
137 | |
138 if (other is VersionRange) { | |
139 // If neither range has a minimum, they'll overlap at some point. | |
140 // | |
141 // ... this ] | |
142 // ... other ] | |
143 if (min == null && other.min == null) return true; | |
144 | |
145 // If this range has a lower minimum than the other range, it overlaps as | |
146 // long as its maximum is higher than or the same as the other range's | |
147 // minimum. | |
148 // | |
149 // [ this ] [ this ] | |
150 // [ other ] [ other ] | |
151 if (min == null || (other.min != null && min < other.min)) { | |
152 if (max == null) return true; | |
153 if (max > other.min) return true; | |
154 if (max < other.min) return false; | |
155 assert(max == other.min); | |
156 return includeMax && other.includeMin; | |
157 } | |
158 | |
159 // If this range has a higher minimum than the other range, it overlaps as | |
160 // long as its minimum is lower than or the same as the other range's | |
161 // maximum. | |
162 // | |
163 // [ this ] [ this ] | |
164 // [ other ] [ other ] | |
Bob Nystrom
2015/05/06 17:30:58
<3 the art.
| |
165 if (other.max == null) return true; | |
166 if (min < other.max) return true; | |
167 if (min > other.max) return false; | |
168 assert(min == other.max); | |
169 return includeMin && other.includeMax; | |
170 } | |
171 | |
172 throw new ArgumentError('Unknown VersionConstraint type $other.'); | |
173 } | |
174 | |
102 VersionConstraint intersect(VersionConstraint other) { | 175 VersionConstraint intersect(VersionConstraint other) { |
103 if (other.isEmpty) return other; | 176 if (other.isEmpty) return other; |
177 if (other is VersionUnion) return other.intersect(this); | |
104 | 178 |
105 // A range and a Version just yields the version if it's in the range. | 179 // A range and a Version just yields the version if it's in the range. |
106 if (other is Version) { | 180 if (other is Version) { |
107 return allows(other) ? other : VersionConstraint.empty; | 181 return allows(other) ? other : VersionConstraint.empty; |
108 } | 182 } |
109 | 183 |
110 if (other is VersionRange) { | 184 if (other is VersionRange) { |
111 // Intersect the two ranges. | 185 // Intersect the two ranges. |
112 var intersectMin = min; | 186 var intersectMin = min; |
113 var intersectIncludeMin = includeMin; | 187 var intersectIncludeMin = includeMin; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 } | 229 } |
156 | 230 |
157 // If we got here, there is an actual range. | 231 // If we got here, there is an actual range. |
158 return new VersionRange(min: intersectMin, max: intersectMax, | 232 return new VersionRange(min: intersectMin, max: intersectMax, |
159 includeMin: intersectIncludeMin, includeMax: intersectIncludeMax); | 233 includeMin: intersectIncludeMin, includeMax: intersectIncludeMax); |
160 } | 234 } |
161 | 235 |
162 throw new ArgumentError('Unknown VersionConstraint type $other.'); | 236 throw new ArgumentError('Unknown VersionConstraint type $other.'); |
163 } | 237 } |
164 | 238 |
239 VersionConstraint union(VersionConstraint other) { | |
240 if (other is Version) { | |
241 if (allows(other)) return this; | |
242 | |
243 if (other == min) { | |
244 return new VersionRange( | |
245 min: this.min, max: this.max, | |
246 includeMin: true, includeMax: this.includeMax); | |
247 } | |
248 | |
249 if (other == max) { | |
250 return new VersionRange( | |
251 min: this.min, max: this.max, | |
252 includeMin: this.includeMin, includeMax: true); | |
253 } | |
254 | |
255 return new VersionConstraint.unionOf([this, other]); | |
256 } | |
257 | |
258 if (other is VersionRange) { | |
259 // If the two ranges don't overlap, we won't be able to create a single | |
260 // VersionRange for both of them. | |
261 var edgesTouch = (max == other.min && (includeMax || other.includeMin)) || | |
262 (min == other.max && (includeMin || other.includeMax)); | |
263 if (!edgesTouch && !allowsAny(other)) { | |
264 return new VersionConstraint.unionOf([this, other]); | |
265 } | |
266 | |
267 var unionMin = min; | |
268 var unionIncludeMin = includeMin; | |
269 var unionMax = max; | |
270 var unionIncludeMax = includeMax; | |
271 | |
272 if (unionMin == null) { | |
273 // Do nothing. | |
274 } else if (other.min == null || other.min < min) { | |
275 unionMin = other.min; | |
276 unionIncludeMin = other.includeMin; | |
277 } else if (min == other.min && other.includeMin) { | |
278 // If the edges are the same but one is inclusive, make it inclusive. | |
279 unionIncludeMin = true; | |
280 } | |
281 | |
282 if (unionMax == null) { | |
283 // Do nothing. | |
284 } else if (other.max == null || other.max > max) { | |
285 unionMax = other.max; | |
286 unionIncludeMax = other.includeMax; | |
287 } else if (max == other.max && other.includeMax) { | |
288 // If the edges are the same but one is inclusive, make it inclusive. | |
289 unionIncludeMax = true; | |
290 } | |
291 | |
292 return new VersionRange(min: unionMin, max: unionMax, | |
293 includeMin: unionIncludeMin, includeMax: unionIncludeMax); | |
294 } | |
295 | |
296 return new VersionConstraint.unionOf([this, other]); | |
297 } | |
298 | |
165 String toString() { | 299 String toString() { |
166 var buffer = new StringBuffer(); | 300 var buffer = new StringBuffer(); |
167 | 301 |
168 if (min != null) { | 302 if (min != null) { |
169 buffer.write(includeMin ? '>=' : '>'); | 303 buffer.write(includeMin ? '>=' : '>'); |
170 buffer.write(min); | 304 buffer.write(min); |
171 } | 305 } |
172 | 306 |
173 if (max != null) { | 307 if (max != null) { |
174 if (min != null) buffer.write(' '); | 308 if (min != null) buffer.write(' '); |
175 buffer.write(includeMax ? '<=' : '<'); | 309 buffer.write(includeMax ? '<=' : '<'); |
176 buffer.write(max); | 310 buffer.write(max); |
177 } | 311 } |
178 | 312 |
179 if (min == null && max == null) buffer.write('any'); | 313 if (min == null && max == null) buffer.write('any'); |
180 return buffer.toString(); | 314 return buffer.toString(); |
181 } | 315 } |
182 } | 316 } |
OLD | NEW |