Chromium Code Reviews| 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 |