| 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; | 5 library pub_semver.src.version; |
| 6 | 6 |
| 7 import 'dart:math'; | 7 import 'dart:math' as math; |
| 8 | 8 |
| 9 import 'package:collection/equality.dart'; | 9 import 'package:collection/equality.dart'; |
| 10 | 10 |
| 11 import 'patterns.dart'; | 11 import 'patterns.dart'; |
| 12 import 'version_constraint.dart'; | 12 import 'version_constraint.dart'; |
| 13 import 'version_range.dart'; | 13 import 'version_range.dart'; |
| 14 | 14 |
| 15 /// The equality operator to use for comparing version components. | 15 /// The equality operator to use for comparing version components. |
| 16 final _equality = const IterableEquality(); | 16 final _equality = const IterableEquality(); |
| 17 | 17 |
| 18 /// A parsed semantic version number. | 18 /// A parsed semantic version number. |
| 19 class Version implements Comparable<Version>, VersionConstraint { | 19 class Version implements Comparable<Version>, VersionConstraint, VersionRange { |
| 20 /// No released version: i.e. "0.0.0". | 20 /// No released version: i.e. "0.0.0". |
| 21 static Version get none => new Version(0, 0, 0); | 21 static Version get none => new Version(0, 0, 0); |
| 22 | 22 |
| 23 /// Compares [a] and [b] to see which takes priority over the other. | 23 /// Compares [a] and [b] to see which takes priority over the other. |
| 24 /// | 24 /// |
| 25 /// Returns `1` if [a] takes priority over [b] and `-1` if vice versa. If | 25 /// Returns `1` if [a] takes priority over [b] and `-1` if vice versa. If |
| 26 /// [a] and [b] are equivalent, returns `0`. | 26 /// [a] and [b] are equivalent, returns `0`. |
| 27 /// | 27 /// |
| 28 /// Unlike [compareTo], which *orders* versions, this determines which | 28 /// Unlike [compareTo], which *orders* versions, this determines which |
| 29 /// version a user is likely to prefer. In particular, it prioritizes | 29 /// version a user is likely to prefer. In particular, it prioritizes |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 /// string or a non-negative integer. It may also be empty, indicating that | 78 /// string or a non-negative integer. It may also be empty, indicating that |
| 79 /// this version has no build identifier. | 79 /// this version has no build identifier. |
| 80 final List build; | 80 final List build; |
| 81 | 81 |
| 82 /// The original string representation of the version number. | 82 /// The original string representation of the version number. |
| 83 /// | 83 /// |
| 84 /// This preserves textual artifacts like leading zeros that may be left out | 84 /// This preserves textual artifacts like leading zeros that may be left out |
| 85 /// of the parsed version. | 85 /// of the parsed version. |
| 86 final String _text; | 86 final String _text; |
| 87 | 87 |
| 88 Version get min => this; |
| 89 Version get max => this; |
| 90 bool get includeMin => true; |
| 91 bool get includeMax => true; |
| 92 |
| 88 Version._(this.major, this.minor, this.patch, String preRelease, String build, | 93 Version._(this.major, this.minor, this.patch, String preRelease, String build, |
| 89 this._text) | 94 this._text) |
| 90 : preRelease = preRelease == null ? [] : _splitParts(preRelease), | 95 : preRelease = preRelease == null ? [] : _splitParts(preRelease), |
| 91 build = build == null ? [] : _splitParts(build) { | 96 build = build == null ? [] : _splitParts(build) { |
| 92 if (major < 0) throw new ArgumentError( | 97 if (major < 0) throw new ArgumentError( |
| 93 'Major version must be non-negative.'); | 98 'Major version must be non-negative.'); |
| 94 if (minor < 0) throw new ArgumentError( | 99 if (minor < 0) throw new ArgumentError( |
| 95 'Minor version must be non-negative.'); | 100 'Minor version must be non-negative.'); |
| 96 if (patch < 0) throw new ArgumentError( | 101 if (patch < 0) throw new ArgumentError( |
| 97 'Patch version must be non-negative.'); | 102 'Patch version must be non-negative.'); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 return _incrementMajor(); | 235 return _incrementMajor(); |
| 231 } | 236 } |
| 232 | 237 |
| 233 Version _incrementMajor() => new Version(major + 1, 0, 0); | 238 Version _incrementMajor() => new Version(major + 1, 0, 0); |
| 234 Version _incrementMinor() => new Version(major, minor + 1, 0); | 239 Version _incrementMinor() => new Version(major, minor + 1, 0); |
| 235 Version _incrementPatch() => new Version(major, minor, patch + 1); | 240 Version _incrementPatch() => new Version(major, minor, patch + 1); |
| 236 | 241 |
| 237 /// Tests if [other] matches this version exactly. | 242 /// Tests if [other] matches this version exactly. |
| 238 bool allows(Version other) => this == other; | 243 bool allows(Version other) => this == other; |
| 239 | 244 |
| 240 VersionConstraint intersect(VersionConstraint other) { | 245 bool allowsAll(VersionConstraint other) => other.isEmpty || other == this; |
| 241 if (other.isEmpty) return other; | |
| 242 | 246 |
| 243 // Intersect a version and a range. | 247 bool allowsAny(VersionConstraint other) => other.allows(this); |
| 244 if (other is VersionRange) return other.intersect(this); | |
| 245 | 248 |
| 246 // Intersecting two versions only works if they are the same. | 249 VersionConstraint intersect(VersionConstraint other) => |
| 247 if (other is Version) { | 250 other.allows(this) ? this : VersionConstraint.empty; |
| 248 return this == other ? this : VersionConstraint.empty; | 251 |
| 252 VersionConstraint union(VersionConstraint other) { |
| 253 if (other.allows(this)) return other; |
| 254 |
| 255 if (other is VersionRange) { |
| 256 if (other.min == this) { |
| 257 return new VersionRange( |
| 258 min: other.min, max: other.max, |
| 259 includeMin: true, includeMax: other.includeMax); |
| 260 } |
| 261 |
| 262 if (other.max == this) { |
| 263 return new VersionRange( |
| 264 min: other.min, max: other.max, |
| 265 includeMin: other.includeMin, includeMax: true); |
| 266 } |
| 249 } | 267 } |
| 250 | 268 |
| 251 throw new ArgumentError( | 269 return new VersionConstraint.unionOf([this, other]); |
| 252 'Unknown VersionConstraint type $other.'); | |
| 253 } | 270 } |
| 254 | 271 |
| 255 int compareTo(Version other) { | 272 int compareTo(Version other) { |
| 256 if (major != other.major) return major.compareTo(other.major); | 273 if (major != other.major) return major.compareTo(other.major); |
| 257 if (minor != other.minor) return minor.compareTo(other.minor); | 274 if (minor != other.minor) return minor.compareTo(other.minor); |
| 258 if (patch != other.patch) return patch.compareTo(other.patch); | 275 if (patch != other.patch) return patch.compareTo(other.patch); |
| 259 | 276 |
| 260 // Pre-releases always come before no pre-release string. | 277 // Pre-releases always come before no pre-release string. |
| 261 if (!isPreRelease && other.isPreRelease) return 1; | 278 if (!isPreRelease && other.isPreRelease) return 1; |
| 262 if (!other.isPreRelease && isPreRelease) return -1; | 279 if (!other.isPreRelease && isPreRelease) return -1; |
| 263 | 280 |
| 264 var comparison = _compareLists(preRelease, other.preRelease); | 281 var comparison = _compareLists(preRelease, other.preRelease); |
| 265 if (comparison != 0) return comparison; | 282 if (comparison != 0) return comparison; |
| 266 | 283 |
| 267 // Builds always come after no build string. | 284 // Builds always come after no build string. |
| 268 if (build.isEmpty && other.build.isNotEmpty) return -1; | 285 if (build.isEmpty && other.build.isNotEmpty) return -1; |
| 269 if (other.build.isEmpty && build.isNotEmpty) return 1; | 286 if (other.build.isEmpty && build.isNotEmpty) return 1; |
| 270 return _compareLists(build, other.build); | 287 return _compareLists(build, other.build); |
| 271 } | 288 } |
| 272 | 289 |
| 273 String toString() => _text; | 290 String toString() => _text; |
| 274 | 291 |
| 275 /// Compares a dot-separated component of two versions. | 292 /// Compares a dot-separated component of two versions. |
| 276 /// | 293 /// |
| 277 /// This is used for the pre-release and build version parts. This follows | 294 /// This is used for the pre-release and build version parts. This follows |
| 278 /// Rule 12 of the Semantic Versioning spec (v2.0.0-rc.1). | 295 /// Rule 12 of the Semantic Versioning spec (v2.0.0-rc.1). |
| 279 int _compareLists(List a, List b) { | 296 int _compareLists(List a, List b) { |
| 280 for (var i = 0; i < max(a.length, b.length); i++) { | 297 for (var i = 0; i < math.max(a.length, b.length); i++) { |
| 281 var aPart = (i < a.length) ? a[i] : null; | 298 var aPart = (i < a.length) ? a[i] : null; |
| 282 var bPart = (i < b.length) ? b[i] : null; | 299 var bPart = (i < b.length) ? b[i] : null; |
| 283 | 300 |
| 284 if (aPart == bPart) continue; | 301 if (aPart == bPart) continue; |
| 285 | 302 |
| 286 // Missing parts come before present ones. | 303 // Missing parts come before present ones. |
| 287 if (aPart == null) return -1; | 304 if (aPart == null) return -1; |
| 288 if (bPart == null) return 1; | 305 if (bPart == null) return 1; |
| 289 | 306 |
| 290 if (aPart is num) { | 307 if (aPart is num) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 303 // Compare two strings. | 320 // Compare two strings. |
| 304 return aPart.compareTo(bPart); | 321 return aPart.compareTo(bPart); |
| 305 } | 322 } |
| 306 } | 323 } |
| 307 } | 324 } |
| 308 | 325 |
| 309 // The lists are entirely equal. | 326 // The lists are entirely equal. |
| 310 return 0; | 327 return 0; |
| 311 } | 328 } |
| 312 } | 329 } |
| OLD | NEW |