Add support for caret (^) operator
parent
ebab9db27a
commit
f363f9d370
|
@ -72,18 +72,19 @@ means any version in the `1.0` development branch. It would match `1.0.0`,
|
||||||
|
|
||||||
Version constraints can be specified in a few different ways.
|
Version constraints can be specified in a few different ways.
|
||||||
|
|
||||||
Name | Example | Description
|
Name | Example | Description
|
||||||
-------------- | ------------------------------------------------------------------ | -----------
|
-------------- | ------------------------------------------------------------------------ | -----------
|
||||||
Exact version | `1.0.2` | You can specify the exact version of a package.
|
Exact version | `1.0.2` | You can specify the exact version of a package.
|
||||||
Range | `>=1.0` `>=1.0 <2.0` <code>>=1.0 <1.1 || >=1.2</code> | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. <br />You can define multiple ranges. Ranges separated by a space (` `) or comma (`,`) will be treated as a **logical AND**. A double pipe (<code>||</code>) will be treated as a **logical OR**. AND has higher precedence than OR.
|
Range | `>=1.0` `>=1.0 <2.0` <code>>=1.0 <1.1 || >=1.2</code> | By using comparison operators you can specify ranges of valid versions. Valid operators are `>`, `>=`, `<`, `<=`, `!=`. <br />You can define multiple ranges. Ranges separated by a space (` `) or comma (`,`) will be treated as a **logical AND**. A double pipe (<code>||</code>) will be treated as a **logical OR**. AND has higher precedence than OR.
|
||||||
Hyphen Range | `1.0 - 2.0` | Inclusive set of versions. Partial versions on the right include are completed with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the `2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to `>=1.0.0 <=2.1.0`.
|
Hyphen Range | `1.0 - 2.0` | Inclusive set of versions. Partial versions on the right include are completed with a wildcard. For example `1.0 - 2.0` is equivalent to `>=1.0.0 <2.1` as the `2.0` becomes `2.0.*`. On the other hand `1.0.0 - 2.1.0` is equivalent to `>=1.0.0 <=2.1.0`.
|
||||||
Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0,<1.1`.
|
Wildcard | `1.0.*` | You can specify a pattern with a `*` wildcard. `1.0.*` is the equivalent of `>=1.0 <1.1`.
|
||||||
Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2,<2.0`. For more details, read the next section below.
|
Tilde Operator | `~1.2` | Very useful for projects that follow semantic versioning. `~1.2` is equivalent to `>=1.2 <2.0`. For more details, read the next section below.
|
||||||
|
Caret Operator | `^1.2.3` | Very useful for projects that follow semantic versioning. `^1.2.3` is equivalent to `>=1.2.3 <2.0`. For more details, read the next section below.
|
||||||
|
|
||||||
### Next Significant Release (Tilde Operator)
|
### Next Significant Release (Tilde and Caret Operators)
|
||||||
|
|
||||||
The `~` operator is best explained by example: `~1.2` is equivalent to
|
The `~` operator is best explained by example: `~1.2` is equivalent to
|
||||||
`>=1.2,<2.0`, while `~1.2.3` is equivalent to `>=1.2.3,<1.3`. As you can see
|
`>=1.2 <2.0.0`, while `~1.2.3` is equivalent to `>=1.2.3 <1.3.0`. As you can see
|
||||||
it is mostly useful for projects respecting [semantic
|
it is mostly useful for projects respecting [semantic
|
||||||
versioning](http://semver.org/). A common usage would be to mark the minimum
|
versioning](http://semver.org/). A common usage would be to mark the minimum
|
||||||
minor version you depend on, like `~1.2` (which allows anything up to, but not
|
minor version you depend on, like `~1.2` (which allows anything up to, but not
|
||||||
|
@ -91,6 +92,12 @@ including, 2.0). Since in theory there should be no backwards compatibility
|
||||||
breaks until 2.0, that works well. Another way of looking at it is that using
|
breaks until 2.0, that works well. Another way of looking at it is that using
|
||||||
`~` specifies a minimum version, but allows the last digit specified to go up.
|
`~` specifies a minimum version, but allows the last digit specified to go up.
|
||||||
|
|
||||||
|
The `^` operator behaves very similarly but it sticks closer to semantic
|
||||||
|
versioning, and will always allow non-breaking updates. For example `^1.2.3`
|
||||||
|
is equivalent to `>=1.2.3 <2.0.0` as none of the releases until 2.0 should
|
||||||
|
break backwards compatibility. For pre-1.0 versions it also acts with safety
|
||||||
|
in mind and treats `^0.3` as `>=0.3.0 <0.4.0`
|
||||||
|
|
||||||
> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint
|
> **Note:** Though `2.0-beta.1` is strictly before `2.0`, a version constraint
|
||||||
> like `~1.2` would not install it. As said above `~1.2` only means the `.2`
|
> like `~1.2` would not install it. As said above `~1.2` only means the `.2`
|
||||||
> can change but the `1.` part is fixed.
|
> can change but the `1.` part is fixed.
|
||||||
|
|
|
@ -330,6 +330,37 @@ class VersionParser
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// match caret constraints
|
||||||
|
if (preg_match('{^\^'.$versionRegex.'($)}i', $constraint, $matches)) {
|
||||||
|
// Work out which position in the version we are operating at
|
||||||
|
if ('0' !== $matches[1] || '' === $matches[2]) {
|
||||||
|
$position = 1;
|
||||||
|
} elseif ('0' !== $matches[2] || '' === $matches[3]) {
|
||||||
|
$position = 2;
|
||||||
|
} else {
|
||||||
|
$position = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the stability suffix
|
||||||
|
$stabilitySuffix = '';
|
||||||
|
if (empty($matches[5]) && empty($matches[7])) {
|
||||||
|
$stabilitySuffix .= '-dev';
|
||||||
|
}
|
||||||
|
|
||||||
|
$lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
|
||||||
|
$lowerBound = new VersionConstraint('>=', $lowVersion);
|
||||||
|
|
||||||
|
// For upper bound, we increment the position of one more significance,
|
||||||
|
// but highPosition = 0 would be illegal
|
||||||
|
$highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
|
||||||
|
$upperBound = new VersionConstraint('<', $highVersion);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$lowerBound,
|
||||||
|
$upperBound
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// match wildcard constraints
|
// match wildcard constraints
|
||||||
if (preg_match('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?\.[xX*]$}', $constraint, $matches)) {
|
if (preg_match('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?\.[xX*]$}', $constraint, $matches)) {
|
||||||
if (isset($matches[3]) && '' !== $matches[3]) {
|
if (isset($matches[3]) && '' !== $matches[3]) {
|
||||||
|
|
|
@ -294,6 +294,39 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider caretConstraints
|
||||||
|
*/
|
||||||
|
public function testParseCaretWildcard($input, $min, $max)
|
||||||
|
{
|
||||||
|
$parser = new VersionParser;
|
||||||
|
if ($min) {
|
||||||
|
$expected = new MultiConstraint(array($min, $max));
|
||||||
|
} else {
|
||||||
|
$expected = $max;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertSame((string) $expected, (string) $parser->parseConstraints($input));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function caretConstraints()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('^1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')),
|
||||||
|
array('^0', new VersionConstraint('>=', '0.0.0.0-dev'), new VersionConstraint('<', '1.0.0.0-dev')),
|
||||||
|
array('^0.0', new VersionConstraint('>=', '0.0.0.0-dev'), new VersionConstraint('<', '0.1.0.0-dev')),
|
||||||
|
array('^1.2', new VersionConstraint('>=', '1.2.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')),
|
||||||
|
array('^1.2.3-beta.2', new VersionConstraint('>=', '1.2.3.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')),
|
||||||
|
array('^1.2.3.4', new VersionConstraint('>=', '1.2.3.4-dev'), new VersionConstraint('<', '2.0.0.0-dev')),
|
||||||
|
array('^1.2.3', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')),
|
||||||
|
array('^0.2.3', new VersionConstraint('>=', '0.2.3.0-dev'), new VersionConstraint('<', '0.3.0.0-dev')),
|
||||||
|
array('^0.2', new VersionConstraint('>=', '0.2.0.0-dev'), new VersionConstraint('<', '0.3.0.0-dev')),
|
||||||
|
array('^0.0.3', new VersionConstraint('>=', '0.0.3.0-dev'), new VersionConstraint('<', '0.0.4.0-dev')),
|
||||||
|
array('^0.0.3-alpha', new VersionConstraint('>=', '0.0.3.0-alpha'), new VersionConstraint('<', '0.0.4.0-dev')),
|
||||||
|
array('^0.0.3-dev', new VersionConstraint('>=', '0.0.3.0-dev'), new VersionConstraint('<', '0.0.4.0-dev')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider hyphenConstraints
|
* @dataProvider hyphenConstraints
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue