Add Version.nextBreaking and "^" operator
diff --git a/README.md b/README.md
index 1cb1527..475c1a3 100644
--- a/README.md
+++ b/README.md
@@ -73,5 +73,23 @@
     specifically selects that unstable version -- they've deliberately opted
     into it.
 
+ *  **There is a notion of compatibility between pre-1.0.0 versions.** Semver 
+    deems all pre-1.0.0 versions to be incompatible.  This means that the only 
+    way to ensure compatibility when depending on a pre-1.0.0 package is to 
+    pin the dependency to an exact version. Pinned version constraints prevent 
+    automatic patch and pre-release updates. To avoid this situation, pub 
+    defines the "next breaking" version to be the version with the left-most 
+    non-zero digit in [major, minor, patch] incremented, and the subsequent 
+    digits reset to zero.  For example, here are some versions along with their 
+    next breaking ones:
+    
+    `0.0.3` -> `0.0.4`
+    `0.7.2-alpha` -> `0.8.0` 
+    `1.2.3` -> `2.0.0` 
+    
+    To make use of this, pub defines a "^" operator which yields a version 
+    constraint greater than or equal to a given version, but less than its next 
+    breaking one.
+    
 [pub]: http://pub.dartlang.org/
 [semver]: http://semver.org/
diff --git a/lib/src/patterns.dart b/lib/src/patterns.dart
index 4a22618..59b0c09 100644
--- a/lib/src/patterns.dart
+++ b/lib/src/patterns.dart
@@ -17,3 +17,6 @@
 /// Parses a comparison operator ("<", ">", "<=", or ">=") at the beginning of
 /// a string.
 final START_COMPARISON = new RegExp(r"^[<>]=?");
+
+/// Parses the "compatible with" operator ("^") at the beginning of a string.
+final START_COMPATIBLE_WITH = new RegExp(r"^\^");
diff --git a/lib/src/version.dart b/lib/src/version.dart
index 866d89c..496178f 100644
--- a/lib/src/version.dart
+++ b/lib/src/version.dart
@@ -189,7 +189,7 @@
       return new Version(major, minor, patch);
     }
 
-    return new Version(major + 1, 0, 0);
+    return _incrementMajor();
   }
 
   /// Gets the next minor version number that follows this one.
@@ -202,7 +202,7 @@
       return new Version(major, minor, patch);
     }
 
-    return new Version(major, minor + 1, 0);
+    return _incrementMinor();
   }
 
   /// Gets the next patch version number that follows this one.
@@ -214,9 +214,31 @@
       return new Version(major, minor, patch);
     }
 
-    return new Version(major, minor, patch + 1);
+    return _incrementPatch();
   }
 
+  /// Gets the next breaking version number that follows this one.
+  ///
+  /// Increments the left-most non-zero digit in ([major], [minor], [patch]).
+  /// In other words, if [major] and [minor] are zero (e.g. 0.0.3), then it 
+  /// increments [patch].  If [major] is zero and [minor] is not (e.g. 0.7.2), 
+  /// then it increments [minor]. Otherwise, it increments [major].
+  Version get nextBreaking {
+    if (major == 0) {
+      if (minor == 0) {
+        return _incrementPatch();
+      }
+      
+      return _incrementMinor();
+    }
+
+    return _incrementMajor();
+  }
+  
+  Version _incrementMajor() => new Version(major + 1, 0, 0);
+  Version _incrementMinor() => new Version(major, minor + 1, 0);
+  Version _incrementPatch() => new Version(major, minor, patch + 1);
+
   /// Tests if [other] matches this version exactly.
   bool allows(Version other) => this == other;
 
diff --git a/lib/src/version_constraint.dart b/lib/src/version_constraint.dart
index 499892e..29dd574 100644
--- a/lib/src/version_constraint.dart
+++ b/lib/src/version_constraint.dart
@@ -23,19 +23,26 @@
 
   /// 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.
+  /// This string is one of:
+  ///   
+  ///   * "any". See [any].
+  ///   * "^" followed by a version string. Versions compatible with the 
+  ///     version number. This allows versions greater than or equal to the 
+  ///     version, and less then the next breaking version (see 
+  ///     [Version.nextBreaking]).
+  ///   * 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
+  ///     ^0.7.2
+  ///     ^1.0.0-alpha
   ///     1.2.3-alpha
   ///     <=5.1.4
   ///     >2.0.4 <= 2.4.6
@@ -82,9 +89,38 @@
       }
       throw "Unreachable.";
     }
+    
+    // Try to parse the "^" operator followed by a version.
+    matchCompatibleWith() {
+      var compatibleWith = START_COMPATIBLE_WITH.firstMatch(text);
+      if (compatibleWith == null) return null;
 
+      var op = compatibleWith[0];
+      text = text.substring(compatibleWith.end);
+      skipWhitespace();
+      
+      var version = matchVersion();
+      if (version == null) {
+        throw new FormatException('Expected version number after "$op" in '
+            '"$originalText", got "$text".');
+      }
+      
+      getCurrentTextIndex() => originalText.length - text.length;
+      var startTextIndex = getCurrentTextIndex();
+      if(constraints.isNotEmpty || text.isNotEmpty) {
+        var constraint = op + originalText.substring(startTextIndex, 
+            getCurrentTextIndex());
+        throw new FormatException('Cannot include other constraints with '
+            '"^" constraint "$constraint" in "$originalText".');
+      }
+      
+      return new VersionRange(min: version, includeMin: true, 
+          max: version.nextBreaking);
+    }
+    
     while (true) {
       skipWhitespace();
+
       if (text.isEmpty) break;
 
       var version = matchVersion();
@@ -98,6 +134,11 @@
         constraints.add(comparison);
         continue;
       }
+      
+      var compatibleWith = matchCompatibleWith();
+      if (compatibleWith != null) {
+        return compatibleWith;
+      }
 
       // If we got here, we couldn't parse the remaining string.
       throw new FormatException('Could not parse version "$originalText". '
diff --git a/test/utils.dart b/test/utils.dart
index da89683..0cc0f65 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -9,6 +9,10 @@
 import 'package:pub_semver/pub_semver.dart';
 
 /// Some stock example versions to use in tests.
+final v003 = new Version.parse('0.0.3');
+final v004 = new Version.parse('0.0.4');
+final v072 = new Version.parse('0.7.2');
+final v080 = new Version.parse('0.8.0');
 final v114 = new Version.parse('1.1.4');
 final v123 = new Version.parse('1.2.3');
 final v124 = new Version.parse('1.2.4');
diff --git a/test/version_constraint_test.dart b/test/version_constraint_test.dart
index df8c099..16a3fdc 100644
--- a/test/version_constraint_test.dart
+++ b/test/version_constraint_test.dart
@@ -123,11 +123,48 @@
           throwsFormatException);
     });
 
+    test('parses a "^" post-1.0.0 version', () {
+      var constraint = new VersionConstraint.parse('^1.2.3');
+
+      expect(constraint, equals(new VersionRange(min: v123, includeMin: true, 
+          max: v123.nextBreaking)));
+    });
+
+    test('parses a "^" pre-1.0.0, post-0.1.0 version', () {
+      var constraint = new VersionConstraint.parse('^0.7.2');
+
+      expect(constraint, equals(new VersionRange(min: v072, includeMin: true, 
+          max: v072.nextBreaking)));
+    });
+
+    test('parses a "^" pre-0.1.0 version', () {
+      var constraint = new VersionConstraint.parse('^0.0.3');
+
+      expect(constraint, equals(new VersionRange(min: v003, includeMin: true, 
+          max: v003.nextBreaking)));
+    });
+
+    test('parses a "^" pre-release version', () {
+      var constraint = new VersionConstraint.parse('^0.7.2-pre+1');
+
+      var min = new Version.parse('0.7.2-pre+1');
+      expect(constraint, equals(new VersionRange(min: min, includeMin: true, 
+          max: min.nextBreaking)));
+    });
+
+    test('does not allow "^" to be mixed with other constraints', () {
+      expect(() => new VersionConstraint.parse('>=1.2.3 ^1.0.0'),
+          throwsFormatException);
+      expect(() => new VersionConstraint.parse('^1.0.0 <1.2.3'),
+          throwsFormatException);
+    });
+
     test('throws FormatException on a bad string', () {
       var bad = [
          "", "   ",               // Empty string.
          "foo",                   // Bad text.
          ">foo",                  // Bad text after operator.
+         "^foo",                  // Bad text after "^".
          "1.0.0 foo", "1.0.0foo", // Bad text after version.
          "anything",              // Bad text after "any".
          "<>1.0.0",               // Multiple operators.
diff --git a/test/version_test.dart b/test/version_test.dart
index b271ecc..527db29 100644
--- a/test/version_test.dart
+++ b/test/version_test.dart
@@ -198,6 +198,18 @@
     expect(new Version.parse('1.2.3+patch').nextPatch, equals(v124));
   });
 
+  test('nextBreaking', () {
+    expect(v123.nextBreaking, equals(v200));
+    expect(v072.nextBreaking, equals(v080));
+    expect(v003.nextBreaking, equals(v004));
+
+    // Removes pre-release version if present.
+    expect(new Version.parse('1.2.3-dev').nextBreaking, equals(v200));
+
+    // Strips build suffix.
+    expect(new Version.parse('1.2.3+patch').nextBreaking, equals(v200));
+  });
+
   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)));