OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library pub_semver.src.version_range; |
| 6 |
| 7 import 'version.dart'; |
| 8 import 'version_constraint.dart'; |
| 9 |
| 10 /// Constrains versions to a fall within a given range. |
| 11 /// |
| 12 /// 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 /// that are allowed. In other words, this allows `>= min, < max`. |
| 15 class VersionRange implements VersionConstraint { |
| 16 /// The minimum end of the range. |
| 17 /// |
| 18 /// If [includeMin] is `true`, this will be the minimum allowed version. |
| 19 /// Otherwise, it will be the highest version below the range that is not |
| 20 /// allowed. |
| 21 /// |
| 22 /// This may be `null` in which case the range has no minimum end and allows |
| 23 /// any version less than the maximum. |
| 24 final Version min; |
| 25 |
| 26 /// The maximum end of the range. |
| 27 /// |
| 28 /// If [includeMax] is `true`, this will be the maximum allowed version. |
| 29 /// Otherwise, it will be the lowest version above the range that is not |
| 30 /// allowed. |
| 31 /// |
| 32 /// This may be `null` in which case the range has no maximum end and allows |
| 33 /// any version greater than the minimum. |
| 34 final Version max; |
| 35 |
| 36 /// If `true` then [min] is allowed by the range. |
| 37 final bool includeMin; |
| 38 |
| 39 /// If `true`, then [max] is allowed by the range. |
| 40 final bool includeMax; |
| 41 |
| 42 /// Creates a new version range from [min] to [max], either inclusive or |
| 43 /// exclusive. |
| 44 /// |
| 45 /// If it is an error if [min] is greater than [max]. |
| 46 /// |
| 47 /// Either [max] or [min] may be omitted to not clamp the range at that end. |
| 48 /// If both are omitted, the range allows all versions. |
| 49 /// |
| 50 /// If [includeMin] is `true`, then the minimum end of the range is inclusive. |
| 51 /// Likewise, passing [includeMax] as `true` makes the upper end inclusive. |
| 52 VersionRange({this.min, this.max, |
| 53 this.includeMin: false, this.includeMax: false}) { |
| 54 if (min != null && max != null && min > max) { |
| 55 throw new ArgumentError( |
| 56 'Minimum version ("$min") must be less than maximum ("$max").'); |
| 57 } |
| 58 } |
| 59 |
| 60 bool operator ==(other) { |
| 61 if (other is! VersionRange) return false; |
| 62 |
| 63 return min == other.min && |
| 64 max == other.max && |
| 65 includeMin == other.includeMin && |
| 66 includeMax == other.includeMax; |
| 67 } |
| 68 |
| 69 bool get isEmpty => false; |
| 70 |
| 71 bool get isAny => min == null && max == null; |
| 72 |
| 73 /// Tests if [other] falls within this version range. |
| 74 bool allows(Version other) { |
| 75 if (min != null) { |
| 76 if (other < min) return false; |
| 77 if (!includeMin && other == min) return false; |
| 78 } |
| 79 |
| 80 if (max != null) { |
| 81 if (other > max) return false; |
| 82 if (!includeMax && other == max) return false; |
| 83 |
| 84 // If the max isn't itself a pre-release, don't allow any pre-release |
| 85 // versions of the max. |
| 86 // |
| 87 // See: https://www.npmjs.org/doc/misc/semver.html |
| 88 if (!includeMax && |
| 89 !max.isPreRelease && other.isPreRelease && |
| 90 other.major == max.major && other.minor == max.minor && |
| 91 other.patch == max.patch) { |
| 92 return false; |
| 93 } |
| 94 } |
| 95 |
| 96 return true; |
| 97 } |
| 98 |
| 99 VersionConstraint intersect(VersionConstraint other) { |
| 100 if (other.isEmpty) return other; |
| 101 |
| 102 // A range and a Version just yields the version if it's in the range. |
| 103 if (other is Version) { |
| 104 return allows(other) ? other : VersionConstraint.empty; |
| 105 } |
| 106 |
| 107 if (other is VersionRange) { |
| 108 // Intersect the two ranges. |
| 109 var intersectMin = min; |
| 110 var intersectIncludeMin = includeMin; |
| 111 var intersectMax = max; |
| 112 var intersectIncludeMax = includeMax; |
| 113 |
| 114 if (other.min == null) { |
| 115 // Do nothing. |
| 116 } else if (intersectMin == null || intersectMin < other.min) { |
| 117 intersectMin = other.min; |
| 118 intersectIncludeMin = other.includeMin; |
| 119 } else if (intersectMin == other.min && !other.includeMin) { |
| 120 // The edges are the same, but one is exclusive, make it exclusive. |
| 121 intersectIncludeMin = false; |
| 122 } |
| 123 |
| 124 if (other.max == null) { |
| 125 // Do nothing. |
| 126 } else if (intersectMax == null || intersectMax > other.max) { |
| 127 intersectMax = other.max; |
| 128 intersectIncludeMax = other.includeMax; |
| 129 } else if (intersectMax == other.max && !other.includeMax) { |
| 130 // The edges are the same, but one is exclusive, make it exclusive. |
| 131 intersectIncludeMax = false; |
| 132 } |
| 133 |
| 134 if (intersectMin == null && intersectMax == null) { |
| 135 // Open range. |
| 136 return new VersionRange(); |
| 137 } |
| 138 |
| 139 // If the range is just a single version. |
| 140 if (intersectMin == intersectMax) { |
| 141 // If both ends are inclusive, allow that version. |
| 142 if (intersectIncludeMin && intersectIncludeMax) return intersectMin; |
| 143 |
| 144 // Otherwise, no versions. |
| 145 return VersionConstraint.empty; |
| 146 } |
| 147 |
| 148 if (intersectMin != null && intersectMax != null && |
| 149 intersectMin > intersectMax) { |
| 150 // Non-overlapping ranges, so empty. |
| 151 return VersionConstraint.empty; |
| 152 } |
| 153 |
| 154 // If we got here, there is an actual range. |
| 155 return new VersionRange(min: intersectMin, max: intersectMax, |
| 156 includeMin: intersectIncludeMin, includeMax: intersectIncludeMax); |
| 157 } |
| 158 |
| 159 throw new ArgumentError('Unknown VersionConstraint type $other.'); |
| 160 } |
| 161 |
| 162 String toString() { |
| 163 var buffer = new StringBuffer(); |
| 164 |
| 165 if (min != null) { |
| 166 buffer.write(includeMin ? '>=' : '>'); |
| 167 buffer.write(min); |
| 168 } |
| 169 |
| 170 if (max != null) { |
| 171 if (min != null) buffer.write(' '); |
| 172 buffer.write(includeMax ? '<=' : '<'); |
| 173 buffer.write(max); |
| 174 } |
| 175 |
| 176 if (min == null && max == null) buffer.write('any'); |
| 177 return buffer.toString(); |
| 178 } |
| 179 } |
OLD | NEW |