From 3d164a9f60e9e5dda8e6702068723ffc18397278 Mon Sep 17 00:00:00 2001
From: "rnystrom@google.com" <rnystrom@google.com>
Date: Wed, 1 Oct 2014 17:57:05 +0000
Subject: [PATCH] Use pub_semver package in pub.

R=nweiz@google.com

Review URL: https://codereview.chromium.org//602253002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge@40849 260f80e4-7a28-3924-810f-c04153c831b5
---
 lib/src/barback.dart                       |   3 +-
 lib/src/cached_package.dart                |   2 +-
 lib/src/command/cache_add.dart             |   3 +-
 lib/src/command/global_activate.dart       |   3 +-
 lib/src/global_packages.dart               |   2 +-
 lib/src/lock_file.dart                     |   2 +-
 lib/src/package.dart                       |   4 +-
 lib/src/preprocess.dart                    |   3 +-
 lib/src/pubspec.dart                       |   2 +-
 lib/src/sdk.dart                           |   2 +-
 lib/src/solver/backtracking_solver.dart    |   3 +-
 lib/src/solver/solve_report.dart           |   3 +-
 lib/src/solver/version_solver.dart         |   4 +-
 lib/src/source.dart                        |   3 +-
 lib/src/source/hosted.dart                 |   2 +-
 lib/src/validator/dependency.dart          |   3 +-
 lib/src/version.dart                       | 592 ---------------------
 test/implicit_barback_dependency_test.dart |   3 +-
 test/implicit_dependency_test.dart         |   3 +-
 test/lock_file_test.dart                   |   2 +-
 test/preprocess_test.dart                  |   2 +-
 test/pubspec_test.dart                     |   2 +-
 test/serve_packages.dart                   |   2 +-
 test/test_pub.dart                         |   2 +-
 test/version_solver_test.dart              |   2 +-
 test/version_test.dart                     | 558 -------------------
 26 files changed, 34 insertions(+), 1178 deletions(-)
 delete mode 100644 lib/src/version.dart
 delete mode 100644 test/version_test.dart

diff --git a/lib/src/barback.dart b/lib/src/barback.dart
index fb4ff51d..33c77542 100644
--- a/lib/src/barback.dart
+++ b/lib/src/barback.dart
@@ -6,8 +6,7 @@ library pub.barback;
 
 import 'package:barback/barback.dart';
 import 'package:path/path.dart' as p;
-
-import 'version.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 /// The currently supported versions of packages that this version of pub works
 /// with.
diff --git a/lib/src/cached_package.dart b/lib/src/cached_package.dart
index 6fac594d..94a500ed 100644
--- a/lib/src/cached_package.dart
+++ b/lib/src/cached_package.dart
@@ -5,13 +5,13 @@
 library pub.cached_package;
 
 import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
 import 'package:yaml/yaml.dart';
 
 import 'barback/transformer_config.dart';
 import 'io.dart';
 import 'package.dart';
 import 'pubspec.dart';
-import 'version.dart';
 
 /// A [Package] whose `lib` directory has been precompiled and cached.
 ///
diff --git a/lib/src/command/cache_add.dart b/lib/src/command/cache_add.dart
index 8c8b4d8a..7a2b4f2b 100644
--- a/lib/src/command/cache_add.dart
+++ b/lib/src/command/cache_add.dart
@@ -6,11 +6,12 @@ library pub.command.cache_add;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../command.dart';
 import '../log.dart' as log;
 import '../package.dart';
 import '../utils.dart';
-import '../version.dart';
 
 /// Handles the `cache add` pub command.
 class CacheAddCommand extends PubCommand {
diff --git a/lib/src/command/global_activate.dart b/lib/src/command/global_activate.dart
index e78641b4..ea8172af 100644
--- a/lib/src/command/global_activate.dart
+++ b/lib/src/command/global_activate.dart
@@ -6,9 +6,10 @@ library pub.command.global_activate;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../command.dart';
 import '../utils.dart';
-import '../version.dart';
 
 /// Handles the `global activate` pub command.
 class GlobalActivateCommand extends PubCommand {
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index c51e545e..73a0c0ab 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -9,6 +9,7 @@ import 'dart:io';
 
 import 'package:path/path.dart' as p;
 import 'package:barback/barback.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 import 'barback/asset_environment.dart';
 import 'entrypoint.dart';
@@ -25,7 +26,6 @@ import 'source/git.dart';
 import 'source/path.dart';
 import 'system_cache.dart';
 import 'utils.dart';
-import 'version.dart';
 
 /// Matches the package name that a binstub was created for inside the contents
 /// of the shell script.
diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart
index 7501951b..99b23327 100644
--- a/lib/src/lock_file.dart
+++ b/lib/src/lock_file.dart
@@ -5,6 +5,7 @@
 library pub.lock_file;
 
 import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
@@ -12,7 +13,6 @@ import 'io.dart';
 import 'package.dart';
 import 'source_registry.dart';
 import 'utils.dart';
-import 'version.dart';
 
 /// A parsed and validated `pubspec.lock` file.
 class LockFile {
diff --git a/lib/src/package.dart b/lib/src/package.dart
index af0c750f..d59a0945 100644
--- a/lib/src/package.dart
+++ b/lib/src/package.dart
@@ -6,8 +6,9 @@ library pub.package;
 
 import 'dart:io';
 
-import 'package:path/path.dart' as p;
 import 'package:barback/barback.dart';
+import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
 
 import 'barback/transformer_id.dart';
 import 'io.dart';
@@ -15,7 +16,6 @@ import 'git.dart' as git;
 import 'pubspec.dart';
 import 'source_registry.dart';
 import 'utils.dart';
-import 'version.dart';
 
 final _README_REGEXP = new RegExp(r"^README($|\.)", caseSensitive: false);
 
diff --git a/lib/src/preprocess.dart b/lib/src/preprocess.dart
index ff14738c..a77b9bd2 100644
--- a/lib/src/preprocess.dart
+++ b/lib/src/preprocess.dart
@@ -4,10 +4,9 @@
 
 library pub.preprocess;
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:string_scanner/string_scanner.dart';
 
-import 'version.dart';
-
 /// Runs a simple preprocessor over [input] to remove sections that are
 /// incompatible with the available barback version.
 ///
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index fad03b2a..55b2df7b 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -5,6 +5,7 @@
 library pub.pubspec;
 
 import 'package:path/path.dart' as path;
+import 'package:pub_semver/pub_semver.dart';
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
@@ -14,7 +15,6 @@ import 'io.dart';
 import 'package.dart';
 import 'source_registry.dart';
 import 'utils.dart';
-import 'version.dart';
 
 /// The parsed contents of a pubspec file.
 ///
diff --git a/lib/src/sdk.dart b/lib/src/sdk.dart
index d47cb52a..3d09163b 100644
--- a/lib/src/sdk.dart
+++ b/lib/src/sdk.dart
@@ -8,9 +8,9 @@ library pub.sdk;
 import 'dart:io';
 
 import 'package:path/path.dart' as path;
+import 'package:pub_semver/pub_semver.dart';
 
 import 'io.dart';
-import 'version.dart';
 
 /// Gets the path to the root directory of the SDK.
 ///
diff --git a/lib/src/solver/backtracking_solver.dart b/lib/src/solver/backtracking_solver.dart
index 8f19a662..241fcb6a 100644
--- a/lib/src/solver/backtracking_solver.dart
+++ b/lib/src/solver/backtracking_solver.dart
@@ -38,6 +38,8 @@ library pub.solver.backtracking_solver;
 import 'dart:async';
 import 'dart:collection' show Queue;
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../barback.dart' as barback;
 import '../exceptions.dart';
 import '../lock_file.dart';
@@ -48,7 +50,6 @@ import '../sdk.dart' as sdk;
 import '../source_registry.dart';
 import '../source/unknown.dart';
 import '../utils.dart';
-import '../version.dart';
 import 'dependency_queue.dart';
 import 'version_queue.dart';
 import 'version_solver.dart';
diff --git a/lib/src/solver/solve_report.dart b/lib/src/solver/solve_report.dart
index 76278a29..2a089b5d 100644
--- a/lib/src/solver/solve_report.dart
+++ b/lib/src/solver/solve_report.dart
@@ -4,12 +4,13 @@
 
 library pub.solver.solve_report;
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../lock_file.dart';
 import '../log.dart' as log;
 import '../package.dart';
 import '../source_registry.dart';
 import '../utils.dart';
-import '../version.dart';
 import 'version_solver.dart';
 
 /// Unlike [SolveResult], which is the static data describing a resolution,
diff --git a/lib/src/solver/version_solver.dart b/lib/src/solver/version_solver.dart
index 5991c9bd..bc2dfb12 100644
--- a/lib/src/solver/version_solver.dart
+++ b/lib/src/solver/version_solver.dart
@@ -7,6 +7,7 @@ library pub.solver.version_solver;
 import 'dart:async';
 import "dart:convert";
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:stack_trace/stack_trace.dart';
 
 import '../exceptions.dart';
@@ -15,7 +16,6 @@ import '../log.dart' as log;
 import '../package.dart';
 import '../pubspec.dart';
 import '../source_registry.dart';
-import '../version.dart';
 import '../utils.dart';
 import 'backtracking_solver.dart';
 import 'solve_report.dart';
@@ -226,7 +226,7 @@ class PubspecCache {
     return source.getVersions(package.name, package.description)
         .then((versions) {
       // Sort by priority so we try preferred versions first.
-      versions.sort(_type == SolveType.DOWNGRADE ? Version.antiPrioritize :
+      versions.sort(_type == SolveType.DOWNGRADE ? Version.antiprioritize :
           Version.prioritize);
 
       var ids = versions.reversed.map(
diff --git a/lib/src/source.dart b/lib/src/source.dart
index 4152384e..7affb689 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -6,10 +6,11 @@ library pub.source;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
+
 import 'package.dart';
 import 'pubspec.dart';
 import 'system_cache.dart';
-import 'version.dart';
 
 /// A source from which to get packages.
 ///
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 2c12dd8c..3bb0ea14 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -10,6 +10,7 @@ import "dart:convert";
 
 import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as path;
+import 'package:pub_semver/pub_semver.dart';
 
 import '../exceptions.dart';
 import '../http.dart';
@@ -18,7 +19,6 @@ import '../log.dart' as log;
 import '../package.dart';
 import '../pubspec.dart';
 import '../utils.dart';
-import '../version.dart';
 import 'cached.dart';
 
 /// A package source that gets packages from a package hosting site that uses
diff --git a/lib/src/validator/dependency.dart b/lib/src/validator/dependency.dart
index ac66d324..19f571d1 100644
--- a/lib/src/validator/dependency.dart
+++ b/lib/src/validator/dependency.dart
@@ -6,11 +6,12 @@ library pub.validator.dependency;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
+
 import '../entrypoint.dart';
 import '../log.dart' as log;
 import '../package.dart';
 import '../validator.dart';
-import '../version.dart';
 
 /// A validator that validates a package's dependencies.
 class DependencyValidator extends Validator {
diff --git a/lib/src/version.dart b/lib/src/version.dart
deleted file mode 100644
index b68c3eda..00000000
--- a/lib/src/version.dart
+++ /dev/null
@@ -1,592 +0,0 @@
-// Copyright (c) 2012, 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.
-
-/// Handles version numbers, following the [Semantic Versioning][semver] spec.
-///
-/// [semver]: http://semver.org/
-library pub.version;
-
-import 'dart:math';
-
-import 'package:collection/equality.dart';
-
-/// Regex that matches a version number at the beginning of a string.
-final _START_VERSION = new RegExp(
-    r'^'                                        // Start at beginning.
-    r'(\d+).(\d+).(\d+)'                        // Version number.
-    r'(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?'    // Pre-release.
-    r'(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?'); // Build.
-
-/// Like [_START_VERSION] but matches the entire string.
-final _COMPLETE_VERSION = new RegExp("${_START_VERSION.pattern}\$");
-
-/// Parses a comparison operator ("<", ">", "<=", or ">=") at the beginning of
-/// a string.
-final _START_COMPARISON = new RegExp(r"^[<>]=?");
-
-/// The equality operator to use for comparing version components.
-final _equality = const IterableEquality();
-
-/// A parsed semantic version number.
-class Version implements Comparable<Version>, VersionConstraint {
-  /// No released version: i.e. "0.0.0".
-  static Version get none => new Version(0, 0, 0);
-
-  /// Compares [a] and [b] to see which takes priority over the other.
-  ///
-  /// Returns `1` if [a] takes priority over [b] and `-1` if vice versa. If
-  /// [a] and [b] are equivalent, returns `0`.
-  ///
-  /// Unlike [compareTo], which *orders* versions, this determines which
-  /// version a user is likely to prefer. In particular, it prioritizes
-  /// pre-release versions lower than stable versions, regardless of their
-  /// version numbers.
-  ///
-  /// When used to sort a list, orders in ascending priority so that the
-  /// highest priority version is *last* in the result.
-  static int prioritize(Version a, Version b) {
-    // Sort all prerelease versions after all normal versions. This way
-    // the solver will prefer stable packages over unstable ones.
-    if (a.isPreRelease && !b.isPreRelease) return -1;
-    if (!a.isPreRelease && b.isPreRelease) return 1;
-
-    return a.compareTo(b);
-  }
-
-  /// Like [proiritize], but lower version numbers are considered greater than
-  /// higher version numbers.
-  ///
-  /// This still considers prerelease versions to be lower than non-prerelease
-  /// versions.
-  static int antiPrioritize(Version a, Version b) {
-    if (a.isPreRelease && !b.isPreRelease) return -1;
-    if (!a.isPreRelease && b.isPreRelease) return 1;
-
-    return b.compareTo(a);
-  }
-
-  /// The major version number: "1" in "1.2.3".
-  final int major;
-
-  /// The minor version number: "2" in "1.2.3".
-  final int minor;
-
-  /// The patch version number: "3" in "1.2.3".
-  final int patch;
-
-  /// The pre-release identifier: "foo" in "1.2.3-foo".
-  ///
-  /// This is split into a list of components, each of which may be either a
-  /// string or a non-negative integer. It may also be empty, indicating that
-  /// this version has no pre-release identifier.
-  final List preRelease;
-
-  /// The build identifier: "foo" in "1.2.3+foo".
-  ///
-  /// This is split into a list of components, each of which may be either a
-  /// string or a non-negative integer. It may also be empty, indicating that
-  /// this version has no build identifier.
-  final List build;
-
-  /// The original string representation of the version number.
-  ///
-  /// This preserves textual artifacts like leading zeros that may be left out
-  /// of the parsed version.
-  final String _text;
-
-  Version._(this.major, this.minor, this.patch, String preRelease, String build,
-            this._text)
-      : preRelease = preRelease == null ? [] : _splitParts(preRelease),
-        build = build == null ? [] : _splitParts(build) {
-    if (major < 0) throw new ArgumentError(
-        'Major version must be non-negative.');
-    if (minor < 0) throw new ArgumentError(
-        'Minor version must be non-negative.');
-    if (patch < 0) throw new ArgumentError(
-        'Patch version must be non-negative.');
-  }
-
-  /// Creates a new [Version] object.
-  factory Version(int major, int minor, int patch, {String pre, String build}) {
-    var text = "$major.$minor.$patch";
-    if (pre != null) text += "-$pre";
-    if (build != null) text += "+$build";
-
-    return new Version._(major, minor, patch, pre, build, text);
-  }
-
-  /// Creates a new [Version] by parsing [text].
-  factory Version.parse(String text) {
-    final match = _COMPLETE_VERSION.firstMatch(text);
-    if (match == null) {
-      throw new FormatException('Could not parse "$text".');
-    }
-
-    try {
-      int major = int.parse(match[1]);
-      int minor = int.parse(match[2]);
-      int patch = int.parse(match[3]);
-
-      String preRelease = match[5];
-      String build = match[8];
-
-      return new Version._(major, minor, patch, preRelease, build, text);
-    } on FormatException catch (ex) {
-      throw new FormatException('Could not parse "$text".');
-    }
-  }
-
-  /// Returns the primary version out of a list of candidates.
-  ///
-  /// This is the highest-numbered stable (non-prerelease) version. If there
-  /// are no stable versions, it's just the highest-numbered version.
-  static Version primary(List<Version> versions) {
-    var primary;
-    for (var version in versions) {
-      if (primary == null || (!version.isPreRelease && primary.isPreRelease) ||
-          (version.isPreRelease == primary.isPreRelease && version > primary)) {
-        primary = version;
-      }
-    }
-    return primary;
-  }
-
-  /// Splits a string of dot-delimited identifiers into their component parts.
-  ///
-  /// Identifiers that are numeric are converted to numbers.
-  static List _splitParts(String text) {
-    return text.split('.').map((part) {
-      try {
-        return int.parse(part);
-      } on FormatException catch (ex) {
-        // Not a number.
-        return part;
-      }
-    }).toList();
-  }
-
-  bool operator ==(other) {
-    if (other is! Version) return false;
-    return major == other.major && minor == other.minor &&
-        patch == other.patch &&
-        _equality.equals(preRelease, other.preRelease) &&
-        _equality.equals(build, other.build);
-  }
-
-  int get hashCode => major ^ minor ^ patch ^ _equality.hash(preRelease) ^
-      _equality.hash(build);
-
-  bool operator <(Version other) => compareTo(other) < 0;
-  bool operator >(Version other) => compareTo(other) > 0;
-  bool operator <=(Version other) => compareTo(other) <= 0;
-  bool operator >=(Version other) => compareTo(other) >= 0;
-
-  bool get isAny => false;
-  bool get isEmpty => false;
-
-  /// Whether or not this is a pre-release version.
-  bool get isPreRelease => preRelease.isNotEmpty;
-
-  /// Gets the next major version number that follows this one.
-  ///
-  /// If this version is a pre-release of a major version release (i.e. the
-  /// minor and patch versions are zero), then it just strips the pre-release
-  /// suffix. Otherwise, it increments the major version and resets the minor
-  /// and patch.
-  Version get nextMajor {
-    if (isPreRelease && minor == 0 && patch == 0) {
-      return new Version(major, minor, patch);
-    }
-
-    return new Version(major + 1, 0, 0);
-  }
-
-  /// Gets the next minor version number that follows this one.
-  ///
-  /// If this version is a pre-release of a minor version release (i.e. the
-  /// patch version is zero), then it just strips the pre-release suffix.
-  /// Otherwise, it increments the minor version and resets the patch.
-  Version get nextMinor {
-    if (isPreRelease && patch == 0) {
-      return new Version(major, minor, patch);
-    }
-
-    return new Version(major, minor + 1, 0);
-  }
-
-  /// Gets the next patch version number that follows this one.
-  ///
-  /// If this version is a pre-release, then it just strips the pre-release
-  /// suffix. Otherwise, it increments the patch version.
-  Version get nextPatch {
-    if (isPreRelease) {
-      return new Version(major, minor, patch);
-    }
-
-    return new Version(major, minor, patch + 1);
-  }
-
-  /// Tests if [other] matches this version exactly.
-  bool allows(Version other) => this == other;
-
-  VersionConstraint intersect(VersionConstraint other) {
-    if (other.isEmpty) return other;
-
-    // Intersect a version and a range.
-    if (other is VersionRange) return other.intersect(this);
-
-    // Intersecting two versions only works if they are the same.
-    if (other is Version) {
-      return this == other ? this : VersionConstraint.empty;
-    }
-
-    throw new ArgumentError(
-        'Unknown VersionConstraint type $other.');
-  }
-
-  int compareTo(Version other) {
-    if (major != other.major) return major.compareTo(other.major);
-    if (minor != other.minor) return minor.compareTo(other.minor);
-    if (patch != other.patch) return patch.compareTo(other.patch);
-
-    // Pre-releases always come before no pre-release string.
-    if (!isPreRelease && other.isPreRelease) return 1;
-    if (!other.isPreRelease && isPreRelease) return -1;
-
-    var comparison = _compareLists(preRelease, other.preRelease);
-    if (comparison != 0) return comparison;
-
-    // Builds always come after no build string.
-    if (build.isEmpty && other.build.isNotEmpty) return -1;
-    if (other.build.isEmpty && build.isNotEmpty) return 1;
-    return _compareLists(build, other.build);
-  }
-
-  String toString() => _text;
-
-  /// Compares a dot-separated component of two versions.
-  ///
-  /// This is used for the pre-release and build version parts. This follows
-  /// Rule 12 of the Semantic Versioning spec (v2.0.0-rc.1).
-  int _compareLists(List a, List b) {
-    for (var i = 0; i < max(a.length, b.length); i++) {
-      var aPart = (i < a.length) ? a[i] : null;
-      var bPart = (i < b.length) ? b[i] : null;
-
-      if (aPart == bPart) continue;
-
-      // Missing parts come before present ones.
-      if (aPart == null) return -1;
-      if (bPart == null) return 1;
-
-      if (aPart is num) {
-        if (bPart is num) {
-          // Compare two numbers.
-          return aPart.compareTo(bPart);
-        } else {
-          // Numbers come before strings.
-          return -1;
-        }
-      } else {
-        if (bPart is num) {
-          // Strings come after numbers.
-          return 1;
-        } else {
-          // Compare two strings.
-          return aPart.compareTo(bPart);
-        }
-      }
-    }
-
-    // The lists are entirely equal.
-    return 0;
-  }
-}
-
-/// A [VersionConstraint] is a predicate that can determine whether a given
-/// version is valid or not.
-///
-/// For example, a ">= 2.0.0" constraint allows any version that is "2.0.0" or
-/// greater. Version objects themselves implement this to match a specific
-/// version.
-abstract class VersionConstraint {
-  /// A [VersionConstraint] that allows all versions.
-  static VersionConstraint any = new VersionRange();
-
-  /// A [VersionConstraint] that allows no versions: i.e. the empty set.
-  static VersionConstraint empty = const _EmptyVersion();
-
-  /// Parses a version constraint.
-  ///
-  /// This string is either "any" or a series of version parts. Each part can
-  /// be one of:
-  ///
-  ///   * A version string like `1.2.3`. In other words, anything that can be
-  ///     parsed by [Version.parse()].
-  ///   * A comparison operator (`<`, `>`, `<=`, or `>=`) followed by a version
-  ///     string.
-  ///
-  /// Whitespace is ignored.
-  ///
-  /// Examples:
-  ///
-  ///     any
-  ///     1.2.3-alpha
-  ///     <=5.1.4
-  ///     >2.0.4 <= 2.4.6
-  factory VersionConstraint.parse(String text) {
-    // Handle the "any" constraint.
-    if (text.trim() == "any") return new VersionRange();
-
-    var originalText = text;
-    var constraints = <VersionConstraint>[];
-
-    void skipWhitespace() {
-      text = text.trim();
-    }
-
-    // Try to parse and consume a version number.
-    Version matchVersion() {
-      var version = _START_VERSION.firstMatch(text);
-      if (version == null) return null;
-
-      text = text.substring(version.end);
-      return new Version.parse(version[0]);
-    }
-
-    // Try to parse and consume a comparison operator followed by a version.
-    VersionConstraint matchComparison() {
-      var comparison = _START_COMPARISON.firstMatch(text);
-      if (comparison == null) return null;
-
-      var op = comparison[0];
-      text = text.substring(comparison.end);
-      skipWhitespace();
-
-      var version = matchVersion();
-      if (version == null) {
-        throw new FormatException('Expected version number after "$op" in '
-            '"$originalText", got "$text".');
-      }
-
-      switch (op) {
-        case '<=':
-          return new VersionRange(max: version, includeMax: true);
-        case '<':
-          return new VersionRange(max: version, includeMax: false);
-        case '>=':
-          return new VersionRange(min: version, includeMin: true);
-        case '>':
-          return new VersionRange(min: version, includeMin: false);
-      }
-      throw "Unreachable.";
-    }
-
-    while (true) {
-      skipWhitespace();
-      if (text.isEmpty) break;
-
-      var version = matchVersion();
-      if (version != null) {
-        constraints.add(version);
-        continue;
-      }
-
-      var comparison = matchComparison();
-      if (comparison != null) {
-        constraints.add(comparison);
-        continue;
-      }
-
-      // If we got here, we couldn't parse the remaining string.
-      throw new FormatException('Could not parse version "$originalText". '
-          'Unknown text at "$text".');
-    }
-
-    if (constraints.isEmpty) {
-      throw new FormatException('Cannot parse an empty string.');
-    }
-
-    return new VersionConstraint.intersection(constraints);
-  }
-
-  /// Creates a new version constraint that is the intersection of
-  /// [constraints].
-  ///
-  /// It only allows versions that all of those constraints allow. If
-  /// constraints is empty, then it returns a VersionConstraint that allows
-  /// all versions.
-  factory VersionConstraint.intersection(
-      Iterable<VersionConstraint> constraints) {
-    var constraint = new VersionRange();
-    for (var other in constraints) {
-      constraint = constraint.intersect(other);
-    }
-    return constraint;
-  }
-
-  /// Returns `true` if this constraint allows no versions.
-  bool get isEmpty;
-
-  /// Returns `true` if this constraint allows all versions.
-  bool get isAny;
-
-  /// Returns `true` if this constraint allows [version].
-  bool allows(Version version);
-
-  /// Creates a new [VersionConstraint] that only allows [Version]s allowed by
-  /// both this and [other].
-  VersionConstraint intersect(VersionConstraint other);
-}
-
-/// 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;
-
-  VersionRange({this.min, this.max,
-      this.includeMin: false, this.includeMax: false}) {
-    if (min != null && max != null && min > max) {
-      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.
-  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();
-  }
-}
-
-class _EmptyVersion implements VersionConstraint {
-  const _EmptyVersion();
-
-  bool get isEmpty => true;
-  bool get isAny => false;
-  bool allows(Version other) => false;
-  VersionConstraint intersect(VersionConstraint other) => this;
-  String toString() => '<empty>';
-}
diff --git a/test/implicit_barback_dependency_test.dart b/test/implicit_barback_dependency_test.dart
index 6965fcde..9b787747 100644
--- a/test/implicit_barback_dependency_test.dart
+++ b/test/implicit_barback_dependency_test.dart
@@ -2,10 +2,11 @@
 // 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.
 
+import 'package:pub_semver/pub_semver.dart';
+
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 import '../lib/src/barback.dart' as barback;
-import '../lib/src/version.dart';
 
 main() {
   initConfig();
diff --git a/test/implicit_dependency_test.dart b/test/implicit_dependency_test.dart
index 34e133f8..0a675667 100644
--- a/test/implicit_dependency_test.dart
+++ b/test/implicit_dependency_test.dart
@@ -2,10 +2,11 @@
 // 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.
 
+import 'package:pub_semver/pub_semver.dart';
+
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 import '../lib/src/barback.dart' as barback;
-import '../lib/src/version.dart';
 
 main() {
   initConfig();
diff --git a/test/lock_file_test.dart b/test/lock_file_test.dart
index 68d04ce0..a2ce2f7a 100644
--- a/test/lock_file_test.dart
+++ b/test/lock_file_test.dart
@@ -6,6 +6,7 @@ library lock_file_test;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:unittest/unittest.dart';
 import 'package:yaml/yaml.dart';
 
@@ -14,7 +15,6 @@ import '../lib/src/package.dart';
 import '../lib/src/pubspec.dart';
 import '../lib/src/source.dart';
 import '../lib/src/source_registry.dart';
-import '../lib/src/version.dart';
 import 'test_pub.dart';
 
 class MockSource extends Source {
diff --git a/test/preprocess_test.dart b/test/preprocess_test.dart
index 98aef17b..4f43dd81 100644
--- a/test/preprocess_test.dart
+++ b/test/preprocess_test.dart
@@ -4,10 +4,10 @@
 
 library pub.test.preprocess_test;
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:unittest/unittest.dart';
 
 import '../lib/src/preprocess.dart';
-import '../lib/src/version.dart';
 import 'test_pub.dart';
 
 main() {
diff --git a/test/pubspec_test.dart b/test/pubspec_test.dart
index fec3077d..67f92766 100644
--- a/test/pubspec_test.dart
+++ b/test/pubspec_test.dart
@@ -6,13 +6,13 @@ library pubspec_test;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:unittest/unittest.dart';
 
 import '../lib/src/package.dart';
 import '../lib/src/pubspec.dart';
 import '../lib/src/source.dart';
 import '../lib/src/source_registry.dart';
-import '../lib/src/version.dart';
 import 'test_pub.dart';
 
 class MockSource extends Source {
diff --git a/test/serve_packages.dart b/test/serve_packages.dart
index 92a319ee..607efd38 100644
--- a/test/serve_packages.dart
+++ b/test/serve_packages.dart
@@ -8,12 +8,12 @@ import 'dart:async';
 import 'dart:convert';
 
 import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 import 'package:yaml/yaml.dart';
 
 import '../lib/src/io.dart';
 import '../lib/src/utils.dart';
-import '../lib/src/version.dart';
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 
diff --git a/test/test_pub.dart b/test/test_pub.dart
index c60d1bbe..6a6fec12 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -16,6 +16,7 @@ import 'dart:math';
 
 import 'package:http/testing.dart';
 import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
 import 'package:scheduled_test/scheduled_process.dart';
 import 'package:scheduled_test/scheduled_server.dart';
 import 'package:scheduled_test/scheduled_stream.dart';
@@ -43,7 +44,6 @@ import '../lib/src/source_registry.dart';
 import '../lib/src/system_cache.dart';
 import '../lib/src/utils.dart';
 import '../lib/src/validator.dart';
-import '../lib/src/version.dart';
 import 'descriptor.dart' as d;
 import 'serve_packages.dart';
 
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index 7673fde1..cdadb67f 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -6,6 +6,7 @@ library pub_upgrade_test;
 
 import 'dart:async';
 
+import 'package:pub_semver/pub_semver.dart';
 import 'package:unittest/unittest.dart';
 
 import '../lib/src/lock_file.dart';
@@ -16,7 +17,6 @@ import '../lib/src/sdk.dart' as sdk;
 import '../lib/src/source/cached.dart';
 import '../lib/src/system_cache.dart';
 import '../lib/src/utils.dart';
-import '../lib/src/version.dart';
 import '../lib/src/solver/version_solver.dart';
 import 'test_pub.dart';
 
diff --git a/test/version_test.dart b/test/version_test.dart
deleted file mode 100644
index 0bfe60eb..00000000
--- a/test/version_test.dart
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright (c) 2012, 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 version_test;
-
-import 'package:unittest/unittest.dart';
-import 'test_pub.dart';
-import '../lib/src/version.dart';
-
-main() {
-  initConfig();
-
-  final v114 = new Version.parse('1.1.4');
-  final v123 = new Version.parse('1.2.3');
-  final v124 = new Version.parse('1.2.4');
-  final v130 = new Version.parse('1.3.0');
-  final v140 = new Version.parse('1.4.0');
-  final v200 = new Version.parse('2.0.0');
-  final v201 = new Version.parse('2.0.1');
-  final v234 = new Version.parse('2.3.4');
-  final v250 = new Version.parse('2.5.0');
-  final v300 = new Version.parse('3.0.0');
-
-  group('Version', () {
-    test('none', () {
-      expect(Version.none.toString(), equals('0.0.0'));
-    });
-
-    group('constructor', () {
-      test('throws on negative numbers', () {
-        throwsIllegalArg(() => new Version(-1, 1, 1));
-        throwsIllegalArg(() => new Version(1, -1, 1));
-        throwsIllegalArg(() => new Version(1, 1, -1));
-      });
-    });
-
-    group('comparison', () {
-      // A correctly sorted list of versions.
-      var versions = [
-        '1.0.0-alpha',
-        '1.0.0-alpha.1',
-        '1.0.0-beta.2',
-        '1.0.0-beta.11',
-        '1.0.0-rc.1',
-        '1.0.0-rc.1+build.1',
-        '1.0.0',
-        '1.0.0+0.3.7',
-        '1.3.7+build',
-        '1.3.7+build.2.b8f12d7',
-        '1.3.7+build.11.e0f985a',
-        '2.0.0',
-        '2.1.0',
-        '2.2.0',
-        '2.11.0',
-        '2.11.1'
-      ];
-
-      test('compareTo()', () {
-        // Ensure that every pair of versions compares in the order that it
-        // appears in the list.
-        for (var i = 0; i < versions.length; i++) {
-          for (var j = 0; j < versions.length; j++) {
-            var a = new Version.parse(versions[i]);
-            var b = new Version.parse(versions[j]);
-            var expectation = i.compareTo(j);
-            expect(a.compareTo(b), equals(expectation));
-          }
-        }
-      });
-
-      test('operators', () {
-        for (var i = 0; i < versions.length; i++) {
-          for (var j = 0; j < versions.length; j++) {
-            var a = new Version.parse(versions[i]);
-            var b = new Version.parse(versions[j]);
-            expect(a < b, equals(i < j));
-            expect(a > b, equals(i > j));
-            expect(a <= b, equals(i <= j));
-            expect(a >= b, equals(i >= j));
-            expect(a == b, equals(i == j));
-            expect(a != b, equals(i != j));
-          }
-        }
-      });
-
-      test('equality', () {
-        expect(new Version.parse('01.2.3'), equals(new Version.parse('1.2.3')));
-        expect(new Version.parse('1.02.3'), equals(new Version.parse('1.2.3')));
-        expect(new Version.parse('1.2.03'), equals(new Version.parse('1.2.3')));
-        expect(new Version.parse('1.2.3-01'),
-            equals(new Version.parse('1.2.3-1')));
-        expect(new Version.parse('1.2.3+01'),
-            equals(new Version.parse('1.2.3+1')));
-      });
-    });
-
-    test('allows()', () {
-      expect(v123.allows(v123), isTrue);
-      expect(v123.allows(v114), isFalse);
-      expect(v123.allows(v124), isFalse);
-    });
-
-    test('intersect()', () {
-      // Intersecting the same version returns the version.
-      expect(v123.intersect(v123), equals(v123));
-
-      // Intersecting a different version allows no versions.
-      expect(v123.intersect(v114).isEmpty, isTrue);
-
-      // Intersecting a range returns the version if the range allows it.
-      expect(v123.intersect(new VersionRange(min: v114, max: v124)),
-          equals(v123));
-
-      // Intersecting a range allows no versions if the range doesn't allow it.
-      expect(v114.intersect(new VersionRange(min: v123, max: v124)).isEmpty,
-          isTrue);
-    });
-
-    test('isEmpty', () {
-      expect(v123.isEmpty, isFalse);
-    });
-
-    test('nextMajor', () {
-      expect(v123.nextMajor, equals(v200));
-      expect(v114.nextMajor, equals(v200));
-      expect(v200.nextMajor, equals(v300));
-
-      // Ignores pre-release if not on a major version.
-      expect(new Version.parse('1.2.3-dev').nextMajor, equals(v200));
-
-      // Just removes it if on a major version.
-      expect(new Version.parse('2.0.0-dev').nextMajor, equals(v200));
-
-      // Strips build suffix.
-      expect(new Version.parse('1.2.3+patch').nextMajor, equals(v200));
-    });
-
-    test('nextMinor', () {
-      expect(v123.nextMinor, equals(v130));
-      expect(v130.nextMinor, equals(v140));
-
-      // Ignores pre-release if not on a minor version.
-      expect(new Version.parse('1.2.3-dev').nextMinor, equals(v130));
-
-      // Just removes it if on a minor version.
-      expect(new Version.parse('1.3.0-dev').nextMinor, equals(v130));
-
-      // Strips build suffix.
-      expect(new Version.parse('1.2.3+patch').nextMinor, equals(v130));
-    });
-
-    test('nextPatch', () {
-      expect(v123.nextPatch, equals(v124));
-      expect(v200.nextPatch, equals(v201));
-
-      // Just removes pre-release version if present.
-      expect(new Version.parse('1.2.4-dev').nextPatch, equals(v124));
-
-      // Strips build suffix.
-      expect(new Version.parse('1.2.3+patch').nextPatch, equals(v124));
-    });
-
-    test('parse()', () {
-      expect(new Version.parse('0.0.0'), equals(new Version(0, 0, 0)));
-      expect(new Version.parse('12.34.56'), equals(new Version(12, 34, 56)));
-
-      expect(new Version.parse('1.2.3-alpha.1'), equals(
-          new Version(1, 2, 3, pre: 'alpha.1')));
-      expect(new Version.parse('1.2.3-x.7.z-92'), equals(
-          new Version(1, 2, 3, pre: 'x.7.z-92')));
-
-      expect(new Version.parse('1.2.3+build.1'), equals(
-          new Version(1, 2, 3, build: 'build.1')));
-      expect(new Version.parse('1.2.3+x.7.z-92'), equals(
-          new Version(1, 2, 3, build: 'x.7.z-92')));
-
-      expect(new Version.parse('1.0.0-rc-1+build-1'), equals(
-          new Version(1, 0, 0, pre: 'rc-1', build: 'build-1')));
-
-      expect(() => new Version.parse('1.0'), throwsFormatException);
-      expect(() => new Version.parse('1.2.3.4'), throwsFormatException);
-      expect(() => new Version.parse('1234'), throwsFormatException);
-      expect(() => new Version.parse('-2.3.4'), throwsFormatException);
-      expect(() => new Version.parse('1.3-pre'), throwsFormatException);
-      expect(() => new Version.parse('1.3+build'), throwsFormatException);
-      expect(() => new Version.parse('1.3+bu?!3ild'), throwsFormatException);
-    });
-
-    test('toString()', () {
-      expect(new Version(0, 0, 0).toString(), equals('0.0.0'));
-      expect(new Version(12, 34, 56).toString(), equals('12.34.56'));
-
-      expect(new Version(1, 2, 3, pre: 'alpha.1').toString(), equals(
-          '1.2.3-alpha.1'));
-      expect(new Version(1, 2, 3, pre: 'x.7.z-92').toString(), equals(
-          '1.2.3-x.7.z-92'));
-
-      expect(new Version(1, 2, 3, build: 'build.1').toString(), equals(
-          '1.2.3+build.1'));
-      expect(new Version(1, 2, 3, pre: 'pre', build: 'bui').toString(), equals(
-          '1.2.3-pre+bui'));
-    });
-  });
-
-  group('VersionRange', () {
-    group('constructor', () {
-      test('takes a min and max', () {
-        var range = new VersionRange(min: v123, max: v124);
-        expect(range.isAny, isFalse);
-        expect(range.min, equals(v123));
-        expect(range.max, equals(v124));
-      });
-
-      test('allows omitting max', () {
-        var range = new VersionRange(min: v123);
-        expect(range.isAny, isFalse);
-        expect(range.min, equals(v123));
-        expect(range.max, isNull);
-      });
-
-      test('allows omitting min and max', () {
-        var range = new VersionRange();
-        expect(range.isAny, isTrue);
-        expect(range.min, isNull);
-        expect(range.max, isNull);
-      });
-
-      test('takes includeMin', () {
-        var range = new VersionRange(min: v123, includeMin: true);
-        expect(range.includeMin, isTrue);
-      });
-
-      test('includeMin defaults to false if omitted', () {
-        var range = new VersionRange(min: v123);
-        expect(range.includeMin, isFalse);
-      });
-
-      test('takes includeMax', () {
-        var range = new VersionRange(max: v123, includeMax: true);
-        expect(range.includeMax, isTrue);
-      });
-
-      test('includeMax defaults to false if omitted', () {
-        var range = new VersionRange(max: v123);
-        expect(range.includeMax, isFalse);
-      });
-
-      test('throws if min > max', () {
-        throwsIllegalArg(() => new VersionRange(min: v124, max: v123));
-      });
-    });
-
-    group('allows()', () {
-      test('version must be greater than min', () {
-        var range = new VersionRange(min: v123);
-
-        expect(range.allows(new Version.parse('1.2.2')), isFalse);
-        expect(range.allows(new Version.parse('1.2.3')), isFalse);
-        expect(range.allows(new Version.parse('1.3.3')), isTrue);
-        expect(range.allows(new Version.parse('2.3.3')), isTrue);
-      });
-
-      test('version must be min or greater if includeMin', () {
-        var range = new VersionRange(min: v123, includeMin: true);
-
-        expect(range.allows(new Version.parse('1.2.2')), isFalse);
-        expect(range.allows(new Version.parse('1.2.3')), isTrue);
-        expect(range.allows(new Version.parse('1.3.3')), isTrue);
-        expect(range.allows(new Version.parse('2.3.3')), isTrue);
-      });
-
-      test('pre-release versions of inclusive min are excluded', () {
-        var range = new VersionRange(min: v123, includeMin: true);
-
-        expect(range.allows(new Version.parse('1.2.3-dev')), isFalse);
-        expect(range.allows(new Version.parse('1.2.4-dev')), isTrue);
-      });
-
-      test('version must be less than max', () {
-        var range = new VersionRange(max: v234);
-
-        expect(range.allows(new Version.parse('2.3.3')), isTrue);
-        expect(range.allows(new Version.parse('2.3.4')), isFalse);
-        expect(range.allows(new Version.parse('2.4.3')), isFalse);
-      });
-
-      test('pre-release versions of non-pre-release max are excluded', () {
-        var range = new VersionRange(max: v234);
-
-        expect(range.allows(new Version.parse('2.3.3')), isTrue);
-        expect(range.allows(new Version.parse('2.3.4-dev')), isFalse);
-        expect(range.allows(new Version.parse('2.3.4')), isFalse);
-      });
-
-      test('pre-release versions of pre-release max are included', () {
-        var range = new VersionRange(max: new Version.parse('2.3.4-dev.2'));
-
-        expect(range.allows(new Version.parse('2.3.4-dev.1')), isTrue);
-        expect(range.allows(new Version.parse('2.3.4-dev.2')), isFalse);
-        expect(range.allows(new Version.parse('2.3.4-dev.3')), isFalse);
-      });
-
-      test('version must be max or less if includeMax', () {
-        var range = new VersionRange(min: v123, max: v234, includeMax: true);
-
-        expect(range.allows(new Version.parse('2.3.3')), isTrue);
-        expect(range.allows(new Version.parse('2.3.4')), isTrue);
-        expect(range.allows(new Version.parse('2.4.3')), isFalse);
-
-        // Pre-releases of the max are allowed.
-        expect(range.allows(new Version.parse('2.3.4-dev')), isTrue);
-      });
-
-      test('has no min if one was not set', () {
-        var range = new VersionRange(max: v123);
-
-        expect(range.allows(new Version.parse('0.0.0')), isTrue);
-        expect(range.allows(new Version.parse('1.2.3')), isFalse);
-      });
-
-      test('has no max if one was not set', () {
-        var range = new VersionRange(min: v123);
-
-        expect(range.allows(new Version.parse('1.2.3')), isFalse);
-        expect(range.allows(new Version.parse('1.3.3')), isTrue);
-        expect(range.allows(new Version.parse('999.3.3')), isTrue);
-      });
-
-      test('allows any version if there is no min or max', () {
-        var range = new VersionRange();
-
-        expect(range.allows(new Version.parse('0.0.0')), isTrue);
-        expect(range.allows(new Version.parse('999.99.9')), isTrue);
-      });
-    });
-
-    group('intersect()', () {
-      test('two overlapping ranges', () {
-        var a = new VersionRange(min: v123, max: v250);
-        var b = new VersionRange(min: v200, max: v300);
-        var intersect = a.intersect(b);
-        expect(intersect.min, equals(v200));
-        expect(intersect.max, equals(v250));
-        expect(intersect.includeMin, isFalse);
-        expect(intersect.includeMax, isFalse);
-      });
-
-      test('a non-overlapping range allows no versions', () {
-        var a = new VersionRange(min: v114, max: v124);
-        var b = new VersionRange(min: v200, max: v250);
-        expect(a.intersect(b).isEmpty, isTrue);
-      });
-
-      test('adjacent ranges allow no versions if exclusive', () {
-        var a = new VersionRange(min: v114, max: v124, includeMax: false);
-        var b = new VersionRange(min: v124, max: v200, includeMin: true);
-        expect(a.intersect(b).isEmpty, isTrue);
-      });
-
-      test('adjacent ranges allow version if inclusive', () {
-        var a = new VersionRange(min: v114, max: v124, includeMax: true);
-        var b = new VersionRange(min: v124, max: v200, includeMin: true);
-        expect(a.intersect(b), equals(v124));
-      });
-
-      test('with an open range', () {
-        var open = new VersionRange();
-        var a = new VersionRange(min: v114, max: v124);
-        expect(open.intersect(open), equals(open));
-        expect(a.intersect(open), equals(a));
-      });
-
-      test('returns the version if the range allows it', () {
-        expect(new VersionRange(min: v114, max: v124).intersect(v123),
-            equals(v123));
-        expect(new VersionRange(min: v123, max: v124).intersect(v114).isEmpty,
-            isTrue);
-      });
-    });
-
-    test('isEmpty', () {
-      expect(new VersionRange().isEmpty, isFalse);
-      expect(new VersionRange(min: v123, max: v124).isEmpty, isFalse);
-    });
-  });
-
-  group('VersionConstraint', () {
-    test('any', () {
-      expect(VersionConstraint.any.isAny, isTrue);
-      expect(VersionConstraint.any, allows([
-        new Version.parse('0.0.0-blah'),
-        new Version.parse('1.2.3'),
-        new Version.parse('12345.678.90')]));
-    });
-
-    test('empty', () {
-      expect(VersionConstraint.empty.isEmpty, isTrue);
-      expect(VersionConstraint.empty.isAny, isFalse);
-      expect(VersionConstraint.empty, doesNotAllow([
-        new Version.parse('0.0.0-blah'),
-        new Version.parse('1.2.3'),
-        new Version.parse('12345.678.90')]));
-    });
-
-    group('parse()', () {
-      test('parses an exact version', () {
-        var constraint = new VersionConstraint.parse('1.2.3-alpha');
-        expect(constraint is Version, isTrue);
-        expect(constraint, equals(new Version(1, 2, 3, pre: 'alpha')));
-      });
-
-      test('parses "any"', () {
-        var constraint = new VersionConstraint.parse('any');
-        expect(constraint is VersionConstraint, isTrue);
-        expect(constraint, allows([
-            new Version.parse('0.0.0'),
-            new Version.parse('1.2.3'),
-            new Version.parse('12345.678.90')]));
-      });
-
-      test('parses a ">" minimum version', () {
-        expect(new VersionConstraint.parse('>1.2.3'), allows([
-            new Version.parse('1.2.3+foo'),
-            new Version.parse('1.2.4')]));
-        expect(new VersionConstraint.parse('>1.2.3'), doesNotAllow([
-            new Version.parse('1.2.1'),
-            new Version.parse('1.2.3-build'),
-            new Version.parse('1.2.3')]));
-      });
-
-      test('parses a ">=" minimum version', () {
-        expect(new VersionConstraint.parse('>=1.2.3'), allows([
-            new Version.parse('1.2.3'),
-            new Version.parse('1.2.3+foo'),
-            new Version.parse('1.2.4')]));
-        expect(new VersionConstraint.parse('>=1.2.3'), doesNotAllow([
-            new Version.parse('1.2.1'),
-            new Version.parse('1.2.3-build')]));
-      });
-
-      test('parses a "<" maximum version', () {
-        expect(new VersionConstraint.parse('<1.2.3'), allows([
-            new Version.parse('1.2.1'),
-            new Version.parse('1.2.2+foo')]));
-        expect(new VersionConstraint.parse('<1.2.3'), doesNotAllow([
-            new Version.parse('1.2.3'),
-            new Version.parse('1.2.3+foo'),
-            new Version.parse('1.2.4')]));
-      });
-
-      test('parses a "<=" maximum version', () {
-        expect(new VersionConstraint.parse('<=1.2.3'), allows([
-            new Version.parse('1.2.1'),
-            new Version.parse('1.2.3-build'),
-            new Version.parse('1.2.3')]));
-        expect(new VersionConstraint.parse('<=1.2.3'), doesNotAllow([
-            new Version.parse('1.2.3+foo'),
-            new Version.parse('1.2.4')]));
-      });
-
-      test('parses a series of space-separated constraints', () {
-        var constraint = new VersionConstraint.parse('>1.0.0 >=1.2.3 <1.3.0');
-        expect(constraint, allows([
-            new Version.parse('1.2.3'),
-            new Version.parse('1.2.5')]));
-        expect(constraint, doesNotAllow([
-            new Version.parse('1.2.3-pre'),
-            new Version.parse('1.3.0'),
-            new Version.parse('3.4.5')]));
-      });
-
-      test('ignores whitespace around operators', () {
-        var constraint = new VersionConstraint.parse(' >1.0.0>=1.2.3 < 1.3.0');
-        expect(constraint, allows([
-            new Version.parse('1.2.3'),
-            new Version.parse('1.2.5')]));
-        expect(constraint, doesNotAllow([
-            new Version.parse('1.2.3-pre'),
-            new Version.parse('1.3.0'),
-            new Version.parse('3.4.5')]));
-      });
-
-      test('does not allow "any" to be mixed with other constraints', () {
-        expect(() => new VersionConstraint.parse('any 1.0.0'),
-            throwsFormatException);
-      });
-
-      test('throws FormatException on a bad string', () {
-        var bad = [
-           "", "   ",               // Empty string.
-           "foo",                   // Bad text.
-           ">foo",                  // Bad text after operator.
-           "1.0.0 foo", "1.0.0foo", // Bad text after version.
-           "anything",              // Bad text after "any".
-           "<>1.0.0",               // Multiple operators.
-           "1.0.0<"                 // Trailing operator.
-        ];
-
-        for (var text in bad) {
-          expect(() => new VersionConstraint.parse(text),
-              throwsFormatException);
-        }
-      });
-    });
-  });
-}
-
-class VersionConstraintMatcher implements Matcher {
-  final List<Version> _expected;
-  final bool _allow;
-
-  VersionConstraintMatcher(this._expected, this._allow);
-
-  bool matches(item, Map matchState) => (item is VersionConstraint) &&
-      _expected.every((version) => item.allows(version) == _allow);
-
-  Description describe(Description description) =>
-      description.add(' ${_allow ? "allows" : "does not allow"} versions');
-
-  Description describeMismatch(item, Description mismatchDescription,
-      Map matchState, bool verbose) {
-    if (item is! VersionConstraint) {
-      mismatchDescription.add('was not a VersionConstraint');
-      return mismatchDescription;
-    }
-
-    bool first = true;
-    for (var version in _expected) {
-      if (item.allows(version) != _allow) {
-        if (first) {
-          if (_allow) {
-            mismatchDescription.addDescriptionOf(item).add('did not allow ');
-          } else {
-            mismatchDescription.addDescriptionOf(item).add('allowed ');
-          }
-        } else {
-          mismatchDescription.add(' and ');
-        }
-        first = false;
-
-        mismatchDescription.add(version.toString());
-      }
-    }
-
-    return mismatchDescription;
-  }
-}
-
-Matcher allows(List<Version> versions) =>
-    new VersionConstraintMatcher(versions, true);
-
-Matcher doesNotAllow(List<Version> versions) =>
-    new VersionConstraintMatcher(versions, false);
-
-throwsIllegalArg(function) {
-  expect(function, throwsA((e) => e is ArgumentError));
-}
-- 
GitLab