| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * Handles version numbers, following the [Semantic Versioning][semver] spec. | 6 * Handles version numbers, following the [Semantic Versioning][semver] spec. |
| 7 * | 7 * |
| 8 * [semver]: http://semver.org/ | 8 * [semver]: http://semver.org/ |
| 9 */ | 9 */ |
| 10 library version; | 10 library version; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 }); | 190 }); |
| 191 } | 191 } |
| 192 } | 192 } |
| 193 | 193 |
| 194 /** | 194 /** |
| 195 * A [VersionConstraint] is a predicate that can determine whether a given | 195 * A [VersionConstraint] is a predicate that can determine whether a given |
| 196 * version is valid or not. For example, a ">= 2.0.0" constraint allows any | 196 * version is valid or not. For example, a ">= 2.0.0" constraint allows any |
| 197 * version that is "2.0.0" or greater. Version objects themselves implement | 197 * version that is "2.0.0" or greater. Version objects themselves implement |
| 198 * this to match a specific version. | 198 * this to match a specific version. |
| 199 */ | 199 */ |
| 200 interface VersionConstraint default _VersionConstraintFactory { | 200 abstract class VersionConstraint { |
| 201 /** | 201 /** |
| 202 * A [VersionConstraint] that allows no versions: i.e. the empty set. | 202 * A [VersionConstraint] that allows no versions: i.e. the empty set. |
| 203 */ | 203 */ |
| 204 VersionConstraint.empty(); | 204 factory VersionConstraint.empty() => const _EmptyVersion(); |
| 205 | 205 |
| 206 /** | 206 /** |
| 207 * Parses a version constraint. This string is a space-separated series of | 207 * Parses a version constraint. This string is a space-separated series of |
| 208 * version parts. Each part can be one of: | 208 * version parts. Each part can be one of: |
| 209 * | 209 * |
| 210 * * A version string like `1.2.3`. In other words, anything that can be | 210 * * A version string like `1.2.3`. In other words, anything that can be |
| 211 * parsed by [Version.parse()]. | 211 * parsed by [Version.parse()]. |
| 212 * * A comparison operator (`<`, `>`, `<=`, or `>=`) followed by a version | 212 * * A comparison operator (`<`, `>`, `<=`, or `>=`) followed by a version |
| 213 * string. There cannot be a space between the operator and the version. | 213 * string. There cannot be a space between the operator and the version. |
| 214 * | 214 * |
| 215 * Examples: | 215 * Examples: |
| 216 * | 216 * |
| 217 * 1.2.3-alpha | 217 * 1.2.3-alpha |
| 218 * <=5.1.4 | 218 * <=5.1.4 |
| 219 * >2.0.4 <=2.4.6 | 219 * >2.0.4 <=2.4.6 |
| 220 */ | 220 */ |
| 221 VersionConstraint.parse(String text); | 221 factory VersionConstraint.parse(String text) { |
| 222 if (text.trim() == '') { |
| 223 throw new FormatException('Cannot parse an empty string.'); |
| 224 } |
| 225 |
| 226 // Split it into space-separated parts. |
| 227 var constraints = <VersionConstraint>[]; |
| 228 for (var part in text.split(' ')) { |
| 229 constraints.add(_parseSingleConstraint(part)); |
| 230 } |
| 231 |
| 232 return new VersionConstraint.intersection(constraints); |
| 233 } |
| 222 | 234 |
| 223 /** | 235 /** |
| 224 * Creates a new version constraint that is the intersection of [constraints]. | 236 * Creates a new version constraint that is the intersection of [constraints]. |
| 225 * It will only allow versions that all of those constraints allow. If | 237 * It will only allow versions that all of those constraints allow. If |
| 226 * constraints is empty, then it returns a VersionConstraint that allows all | 238 * constraints is empty, then it returns a VersionConstraint that allows all |
| 227 * versions. | 239 * versions. |
| 228 */ | 240 */ |
| 229 VersionConstraint.intersect(Collection<VersionConstraint> constraints); | 241 factory VersionConstraint.intersection( |
| 242 Collection<VersionConstraint> constraints) { |
| 243 var constraint = new VersionRange(); |
| 244 for (var other in constraints) { |
| 245 constraint = constraint.intersect(other); |
| 246 } |
| 247 return constraint; |
| 248 } |
| 230 | 249 |
| 231 /** | 250 /** |
| 232 * Returns `true` if this constraint allows no versions. | 251 * Returns `true` if this constraint allows no versions. |
| 233 */ | 252 */ |
| 234 bool get isEmpty; | 253 bool get isEmpty; |
| 235 | 254 |
| 236 /** | 255 /** |
| 237 * Returns `true` if this constraint allows [version]. | 256 * Returns `true` if this constraint allows [version]. |
| 238 */ | 257 */ |
| 239 bool allows(Version version); | 258 bool allows(Version version); |
| 240 | 259 |
| 241 /** | 260 /** |
| 242 * Creates a new [VersionConstraint] that only allows [Version]s allowed by | 261 * Creates a new [VersionConstraint] that only allows [Version]s allowed by |
| 243 * both this and [other]. | 262 * both this and [other]. |
| 244 */ | 263 */ |
| 245 VersionConstraint intersect(VersionConstraint other); | 264 VersionConstraint intersect(VersionConstraint other); |
| 265 |
| 266 static VersionConstraint _parseSingleConstraint(String text) { |
| 267 if (text == 'any') { |
| 268 return new VersionRange(); |
| 269 } |
| 270 |
| 271 // TODO(rnystrom): Consider other syntaxes for version constraints. This |
| 272 // one is whitespace sensitive (you can't do "< 1.2.3") and "<" is |
| 273 // unfortunately meaningful in YAML, requiring it to be quoted in a |
| 274 // pubspec. |
| 275 // See if it's a comparison operator followed by a version, like ">1.2.3". |
| 276 var match = new RegExp(r"^([<>]=?)?(.*)$").firstMatch(text); |
| 277 if (match != null) { |
| 278 var comparison = match[1]; |
| 279 var version = new Version.parse(match[2]); |
| 280 switch (match[1]) { |
| 281 case '<=': return new VersionRange(max: version, includeMax: true); |
| 282 case '<': return new VersionRange(max: version, includeMax: false); |
| 283 case '>=': return new VersionRange(min: version, includeMin: true); |
| 284 case '>': return new VersionRange(min: version, includeMin: false); |
| 285 } |
| 286 } |
| 287 |
| 288 // Otherwise, it must be an explicit version. |
| 289 return new Version.parse(text); |
| 290 } |
| 246 } | 291 } |
| 247 | 292 |
| 248 /** | 293 /** |
| 249 * Constrains versions to a fall within a given range. If there is a minimum, | 294 * Constrains versions to a fall within a given range. If there is a minimum, |
| 250 * then this only allows versions that are at that minimum or greater. If there | 295 * then this only allows versions that are at that minimum or greater. If there |
| 251 * is a maximum, then only versions less than that are allowed. In other words, | 296 * is a maximum, then only versions less than that are allowed. In other words, |
| 252 * this allows `>= min, < max`. | 297 * this allows `>= min, < max`. |
| 253 */ | 298 */ |
| 254 class VersionRange implements VersionConstraint { | 299 class VersionRange implements VersionConstraint { |
| 255 final Version min; | 300 final Version min; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 } | 412 } |
| 368 | 413 |
| 369 class _EmptyVersion implements VersionConstraint { | 414 class _EmptyVersion implements VersionConstraint { |
| 370 const _EmptyVersion(); | 415 const _EmptyVersion(); |
| 371 | 416 |
| 372 bool get isEmpty => true; | 417 bool get isEmpty => true; |
| 373 bool allows(Version other) => false; | 418 bool allows(Version other) => false; |
| 374 VersionConstraint intersect(VersionConstraint other) => this; | 419 VersionConstraint intersect(VersionConstraint other) => this; |
| 375 String toString() => '<empty>'; | 420 String toString() => '<empty>'; |
| 376 } | 421 } |
| 377 | |
| 378 class _VersionConstraintFactory { | |
| 379 factory VersionConstraint.empty() => const _EmptyVersion(); | |
| 380 | |
| 381 factory VersionConstraint.parse(String text) { | |
| 382 if (text.trim() == '') { | |
| 383 throw new FormatException('Cannot parse an empty string.'); | |
| 384 } | |
| 385 | |
| 386 // Split it into space-separated parts. | |
| 387 var constraints = <VersionConstraint>[]; | |
| 388 for (var part in text.split(' ')) { | |
| 389 constraints.add(parseSingleConstraint(part)); | |
| 390 } | |
| 391 | |
| 392 return new VersionConstraint.intersect(constraints); | |
| 393 } | |
| 394 | |
| 395 factory VersionConstraint.intersect( | |
| 396 Collection<VersionConstraint> constraints) { | |
| 397 var constraint = new VersionRange(); | |
| 398 for (var other in constraints) { | |
| 399 constraint = constraint.intersect(other); | |
| 400 } | |
| 401 return constraint; | |
| 402 } | |
| 403 | |
| 404 static VersionConstraint parseSingleConstraint(String text) { | |
| 405 if (text == 'any') { | |
| 406 return new VersionRange(); | |
| 407 } | |
| 408 | |
| 409 // TODO(rnystrom): Consider other syntaxes for version constraints. This | |
| 410 // one is whitespace sensitive (you can't do "< 1.2.3") and "<" is | |
| 411 // unfortunately meaningful in YAML, requiring it to be quoted in a | |
| 412 // pubspec. | |
| 413 // See if it's a comparison operator followed by a version, like ">1.2.3". | |
| 414 var match = new RegExp(r"^([<>]=?)?(.*)$").firstMatch(text); | |
| 415 if (match != null) { | |
| 416 var comparison = match[1]; | |
| 417 var version = new Version.parse(match[2]); | |
| 418 switch (match[1]) { | |
| 419 case '<=': return new VersionRange(max: version, includeMax: true); | |
| 420 case '<': return new VersionRange(max: version, includeMax: false); | |
| 421 case '>=': return new VersionRange(min: version, includeMin: true); | |
| 422 case '>': return new VersionRange(min: version, includeMin: false); | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 // Otherwise, it must be an explicit version. | |
| 427 return new Version.parse(text); | |
| 428 } | |
| 429 } | |
| OLD | NEW |