Chromium Code Reviews| Index: lib/src/version_range.dart |
| diff --git a/lib/src/version_range.dart b/lib/src/version_range.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..68754573c8b677c13513918a0cebdfae3f38e3eb |
| --- /dev/null |
| +++ b/lib/src/version_range.dart |
| @@ -0,0 +1,149 @@ |
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +library pub_semver.src.version_range; |
| + |
| +import 'version.dart'; |
| +import 'version_constraint.dart'; |
| + |
| +/// Constrains versions to a fall within a given range. |
| +/// |
| +/// If there is a minimum, then this only allows versions that are at that |
| +/// minimum or greater. If there is a maximum, then only versions less than |
| +/// that are allowed. In other words, this allows `>= min, < max`. |
| +class VersionRange implements VersionConstraint { |
| + final Version min; |
| + final Version max; |
| + final bool includeMin; |
| + final bool includeMax; |
|
nweiz
2014/09/25 22:52:02
Document these, especially what it means for [min]
Bob Nystrom
2014/09/26 19:41:07
Done.
|
| + |
| + VersionRange({this.min, this.max, |
|
nweiz
2014/09/25 22:52:02
Document this.
Bob Nystrom
2014/09/26 19:41:07
Done.
|
| + this.includeMin: false, this.includeMax: false}) { |
| + if (min != null && max != null && min > max) { |
|
nweiz
2014/09/25 22:52:02
Nit: short-circuit to save a line.
Bob Nystrom
2014/09/26 19:41:07
I would in most cases, but I think this is a bit e
|
| + throw new ArgumentError( |
| + 'Minimum version ("$min") must be less than maximum ("$max").'); |
| + } |
| + } |
| + |
| + bool operator ==(other) { |
| + if (other is! VersionRange) return false; |
| + |
| + return min == other.min && |
| + max == other.max && |
| + includeMin == other.includeMin && |
| + includeMax == other.includeMax; |
| + } |
| + |
| + bool get isEmpty => false; |
| + |
| + bool get isAny => min == null && max == null; |
| + |
| + /// Tests if [other] matches falls within this version range. |
|
nweiz
2014/09/25 22:52:02
-"matches"
Bob Nystrom
2014/09/26 19:41:07
Done.
|
| + bool allows(Version other) { |
| + if (min != null) { |
| + if (other < min) return false; |
| + if (!includeMin && other == min) return false; |
| + } |
| + |
| + if (max != null) { |
| + if (other > max) return false; |
| + if (!includeMax && other == max) return false; |
| + |
| + // If the max isn't itself a pre-release, don't allow any pre-release |
| + // versions of the max. |
| + // |
| + // See: https://www.npmjs.org/doc/misc/semver.html |
| + if (!includeMax && |
| + !max.isPreRelease && other.isPreRelease && |
| + other.major == max.major && other.minor == max.minor && |
| + other.patch == max.patch) { |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| + } |
| + |
| + VersionConstraint intersect(VersionConstraint other) { |
| + if (other.isEmpty) return other; |
| + |
| + // A range and a Version just yields the version if it's in the range. |
| + if (other is Version) { |
| + return allows(other) ? other : VersionConstraint.empty; |
| + } |
| + |
| + if (other is VersionRange) { |
| + // Intersect the two ranges. |
| + var intersectMin = min; |
| + var intersectIncludeMin = includeMin; |
| + var intersectMax = max; |
| + var intersectIncludeMax = includeMax; |
| + |
| + if (other.min == null) { |
| + // Do nothing. |
| + } else if (intersectMin == null || intersectMin < other.min) { |
| + intersectMin = other.min; |
| + intersectIncludeMin = other.includeMin; |
| + } else if (intersectMin == other.min && !other.includeMin) { |
| + // The edges are the same, but one is exclusive, make it exclusive. |
| + intersectIncludeMin = false; |
| + } |
| + |
| + if (other.max == null) { |
| + // Do nothing. |
| + } else if (intersectMax == null || intersectMax > other.max) { |
| + intersectMax = other.max; |
| + intersectIncludeMax = other.includeMax; |
| + } else if (intersectMax == other.max && !other.includeMax) { |
| + // The edges are the same, but one is exclusive, make it exclusive. |
| + intersectIncludeMax = false; |
| + } |
| + |
| + if (intersectMin == null && intersectMax == null) { |
| + // Open range. |
| + return new VersionRange(); |
| + } |
| + |
| + // If the range is just a single version. |
| + if (intersectMin == intersectMax) { |
| + // If both ends are inclusive, allow that version. |
| + if (intersectIncludeMin && intersectIncludeMax) return intersectMin; |
| + |
| + // Otherwise, no versions. |
| + return VersionConstraint.empty; |
| + } |
| + |
| + if (intersectMin != null && intersectMax != null && |
| + intersectMin > intersectMax) { |
| + // Non-overlapping ranges, so empty. |
| + return VersionConstraint.empty; |
| + } |
| + |
| + // If we got here, there is an actual range. |
| + return new VersionRange(min: intersectMin, max: intersectMax, |
| + includeMin: intersectIncludeMin, includeMax: intersectIncludeMax); |
| + } |
| + |
| + throw new ArgumentError( |
| + 'Unknown VersionConstraint type $other.'); |
| + } |
| + |
| + String toString() { |
| + var buffer = new StringBuffer(); |
| + |
| + if (min != null) { |
| + buffer.write(includeMin ? '>=' : '>'); |
| + buffer.write(min); |
| + } |
| + |
| + if (max != null) { |
| + if (min != null) buffer.write(' '); |
| + buffer.write(includeMax ? '<=' : '<'); |
| + buffer.write(max); |
| + } |
| + |
| + if (min == null && max == null) buffer.write('any'); |
| + return buffer.toString(); |
| + } |
| +} |