diff --git a/composer.json b/composer.json index 4ba003887..b4e372ac4 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "require": { "php": ">=5.3.2", "justinrainbow/json-schema": "^1.4.4", - "composer/spdx-licenses": "~1.0", + "composer/spdx-licenses": "^1.0", + "composer/semver": "^1.0", "seld/jsonlint": "~1.0", "symfony/console": "~2.5", "symfony/finder": "~2.2", diff --git a/composer.lock b/composer.lock index 0c6108927..25dc03c27 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,69 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3024e89a7e808b8dece156112459a7ea", - "content-hash": "01608741fe66bb9528d7c77c0a422965", + "hash": "af3956ae4c1a09e3e72cd66346a6176d", "packages": [ + { + "name": "composer/semver", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/d0e1ccc6d44ab318b758d709e19176037da6b1ba", + "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com" + }, + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2015-09-21 09:42:36" + }, { "name": "composer/spdx-licenses", "version": "1.1.1", diff --git a/src/Composer/Package/LinkConstraint/EmptyConstraint.php b/src/Composer/Package/LinkConstraint/EmptyConstraint.php index ca1c75ff5..43cc65163 100644 --- a/src/Composer/Package/LinkConstraint/EmptyConstraint.php +++ b/src/Composer/Package/LinkConstraint/EmptyConstraint.php @@ -12,36 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\EmptyConstraint as BaseEmptyConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED); + /** - * Defines an absence of constraints - * - * @author Jordi Boggiano + * @deprecated use Composer\Semver\Constraint\EmptyConstraint instead */ -class EmptyConstraint implements LinkConstraintInterface +class EmptyConstraint extends BaseEmptyConstraint { - protected $prettyString; - - public function matches(LinkConstraintInterface $provider) - { - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - public function __toString() - { - return '[]'; - } } diff --git a/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php b/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php index 199c9fc42..bac98c6f9 100644 --- a/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php +++ b/src/Composer/Package/LinkConstraint/LinkConstraintInterface.php @@ -12,15 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\ConstraintInterface; + +@trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED); + /** - * Defines a constraint on a link between two packages. - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\ConstraintInterface instead */ -interface LinkConstraintInterface +interface LinkConstraintInterface extends ConstraintInterface { - public function matches(LinkConstraintInterface $provider); - public function setPrettyString($prettyString); - public function getPrettyString(); - public function __toString(); } diff --git a/src/Composer/Package/LinkConstraint/MultiConstraint.php b/src/Composer/Package/LinkConstraint/MultiConstraint.php index 3871aeb2f..296076b18 100644 --- a/src/Composer/Package/LinkConstraint/MultiConstraint.php +++ b/src/Composer/Package/LinkConstraint/MultiConstraint.php @@ -12,72 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\MultiConstraint as BaseMultiConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED); + /** - * Defines a conjunctive or disjunctive set of constraints on the target of a package link - * - * @author Nils Adermann - * @author Jordi Boggiano + * @deprecated use Composer\Semver\Constraint\MultiConstraint instead */ -class MultiConstraint implements LinkConstraintInterface +class MultiConstraint extends BaseMultiConstraint { - protected $constraints; - protected $prettyString; - protected $conjunctive; - - /** - * Sets operator and version to compare a package with - * - * @param array $constraints A set of constraints - * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive - */ - public function __construct(array $constraints, $conjunctive = true) - { - $this->constraints = $constraints; - $this->conjunctive = $conjunctive; - } - - public function matches(LinkConstraintInterface $provider) - { - if (false === $this->conjunctive) { - foreach ($this->constraints as $constraint) { - if ($constraint->matches($provider)) { - return true; - } - } - - return false; - } - - foreach ($this->constraints as $constraint) { - if (!$constraint->matches($provider)) { - return false; - } - } - - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - public function __toString() - { - $constraints = array(); - foreach ($this->constraints as $constraint) { - $constraints[] = $constraint->__toString(); - } - - return '['.implode($this->conjunctive ? ' ' : ' || ', $constraints).']'; - } } diff --git a/src/Composer/Package/LinkConstraint/SpecificConstraint.php b/src/Composer/Package/LinkConstraint/SpecificConstraint.php index e0904dbbf..409f0a440 100644 --- a/src/Composer/Package/LinkConstraint/SpecificConstraint.php +++ b/src/Composer/Package/LinkConstraint/SpecificConstraint.php @@ -12,42 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\AbstractConstraint; + +@trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, use Composer\Semver\Constraint\AbstractConstraint instead.', E_USER_DEPRECATED); + /** - * Provides a common basis for specific package link constraints - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\AbstractConstraint instead */ -abstract class SpecificConstraint implements LinkConstraintInterface +abstract class SpecificConstraint extends AbstractConstraint { - protected $prettyString; - - public function matches(LinkConstraintInterface $provider) - { - if ($provider instanceof MultiConstraint) { - // turn matching around to find a match - return $provider->matches($this); - } elseif ($provider instanceof $this) { - return $this->matchSpecific($provider); - } - - return true; - } - - public function setPrettyString($prettyString) - { - $this->prettyString = $prettyString; - } - - public function getPrettyString() - { - if ($this->prettyString) { - return $this->prettyString; - } - - return $this->__toString(); - } - - // implementations must implement a method of this format: - // not declared abstract here because type hinting violates parameter coherence (TODO right word?) - // public function matchSpecific( $provider); } diff --git a/src/Composer/Package/LinkConstraint/VersionConstraint.php b/src/Composer/Package/LinkConstraint/VersionConstraint.php index 4b6cf2ad7..45d471254 100644 --- a/src/Composer/Package/LinkConstraint/VersionConstraint.php +++ b/src/Composer/Package/LinkConstraint/VersionConstraint.php @@ -12,116 +12,13 @@ namespace Composer\Package\LinkConstraint; +use Composer\Semver\Constraint\Constraint; + +@trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED); + /** - * Constrains a package link based on package version - * - * Version numbers must be compatible with version_compare - * - * @author Nils Adermann + * @deprecated use Composer\Semver\Constraint\Constraint instead */ -class VersionConstraint extends SpecificConstraint +class VersionConstraint extends Constraint { - const OP_EQ = 0; - const OP_LT = 1; - const OP_LE = 2; - const OP_GT = 3; - const OP_GE = 4; - const OP_NE = 5; - - private static $transOpStr = array( - '=' => self::OP_EQ, - '==' => self::OP_EQ, - '<' => self::OP_LT, - '<=' => self::OP_LE, - '>' => self::OP_GT, - '>=' => self::OP_GE, - '<>' => self::OP_NE, - '!=' => self::OP_NE, - ); - - private static $transOpInt = array( - self::OP_EQ => '==', - self::OP_LT => '<', - self::OP_LE => '<=', - self::OP_GT => '>', - self::OP_GE => '>=', - self::OP_NE => '!=', - ); - - private $operator; - private $version; - - /** - * Sets operator and version to compare a package with - * - * @param string $operator A comparison operator - * @param string $version A version to compare to - */ - public function __construct($operator, $version) - { - $this->operator = self::$transOpStr[$operator]; - $this->version = $version; - } - - public function versionCompare($a, $b, $operator, $compareBranches = false) - { - $aIsBranch = 'dev-' === substr($a, 0, 4); - $bIsBranch = 'dev-' === substr($b, 0, 4); - if ($aIsBranch && $bIsBranch) { - return $operator == '==' && $a === $b; - } - - // when branches are not comparable, we make sure dev branches never match anything - if (!$compareBranches && ($aIsBranch || $bIsBranch)) { - return false; - } - - return version_compare($a, $b, $operator); - } - - /** - * @param VersionConstraint $provider - * @param bool $compareBranches - * @return bool - */ - public function matchSpecific(VersionConstraint $provider, $compareBranches = false) - { - $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]); - $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]); - - $isEqualOp = self::OP_EQ === $this->operator; - $isNonEqualOp = self::OP_NE === $this->operator; - $isProviderEqualOp = self::OP_EQ === $provider->operator; - $isProviderNonEqualOp = self::OP_NE === $provider->operator; - - // '!=' operator is match when other operator is not '==' operator or version is not match - // these kinds of comparisons always have a solution - if ($isNonEqualOp || $isProviderNonEqualOp) { - return !$isEqualOp && !$isProviderEqualOp - || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); - } - - // an example for the condition is <= 2.0 & < 1.0 - // these kinds of comparisons always have a solution - if ($this->operator !== self::OP_EQ && $noEqualOp == $providerNoEqualOp) { - return true; - } - - if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) { - // special case, e.g. require >= 1.0 and provide < 1.0 - // 1.0 >= 1.0 but 1.0 is outside of the provided interval - if ($provider->version == $this->version && self::$transOpInt[$provider->operator] == $providerNoEqualOp && self::$transOpInt[$this->operator] != $noEqualOp) { - return false; - } - - return true; - } - - return false; - } - - public function __toString() - { - return self::$transOpInt[$this->operator].' '.$this->version; - } } diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index cacc0b118..4c29599c8 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -12,513 +12,14 @@ namespace Composer\Package\Version; -use Composer\Package\PackageInterface; -use Composer\Package\Link; -use Composer\Package\LinkConstraint\EmptyConstraint; -use Composer\Package\LinkConstraint\MultiConstraint; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\Loader\ArrayLoader; +use Composer\Semver\VersionParser as BaseVersionParser; -/** - * Version parser - * - * @author Jordi Boggiano - */ -class VersionParser +class VersionParser extends BaseVersionParser { - private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?'; - - private static $stabilities = array( - 'stable', 'RC', 'beta', 'alpha', 'dev', - ); - /** - * Returns the stability of a version + * @param array $pairs * - * @param string $version - * @return string - */ - public static function parseStability($version) - { - $version = preg_replace('{#.+$}i', '', $version); - - if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) { - return 'dev'; - } - - preg_match('{'.self::$modifierRegex.'$}i', strtolower($version), $match); - if (!empty($match[3])) { - return 'dev'; - } - - if (!empty($match[1])) { - if ('beta' === $match[1] || 'b' === $match[1]) { - return 'beta'; - } - if ('alpha' === $match[1] || 'a' === $match[1]) { - return 'alpha'; - } - if ('rc' === $match[1]) { - return 'RC'; - } - } - - return 'stable'; - } - - public static function normalizeStability($stability) - { - $stability = strtolower($stability); - - return $stability === 'rc' ? 'RC' : $stability; - } - - /** - * @deprecated Use PackageInterface::getFullPrettyVersion instead - */ - public static function formatVersion(PackageInterface $package, $truncate = true) - { - trigger_error(__METHOD__.' is deprecated. Use '. - '\Composer\Package\PackageInterface::getFullPrettyVersion() instead', E_USER_DEPRECATED); - - return $package->getFullPrettyVersion($truncate); - } - - /** - * Normalizes a version string to be able to perform comparisons on it - * - * @param string $version - * @param string $fullVersion optional complete version string to give more context - * @throws \UnexpectedValueException - * @return string - */ - public function normalize($version, $fullVersion = null) - { - $version = trim($version); - if (null === $fullVersion) { - $fullVersion = $version; - } - - // ignore aliases and just assume the alias is required instead of the source - if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $version, $match)) { - $version = $match[1]; - } - - // ignore build metadata - if (preg_match('{^([^,\s+]+)\+[^\s]+$}', $version, $match)) { - $version = $match[1]; - } - - // match master-like branches - if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) { - return '9999999-dev'; - } - - if ('dev-' === strtolower(substr($version, 0, 4))) { - return 'dev-'.substr($version, 4); - } - - // match classical versioning - if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) { - $version = $matches[1] - .(!empty($matches[2]) ? $matches[2] : '.0') - .(!empty($matches[3]) ? $matches[3] : '.0') - .(!empty($matches[4]) ? $matches[4] : '.0'); - $index = 5; - } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)'.self::$modifierRegex.'$}i', $version, $matches)) { // match date-based versioning - $version = preg_replace('{\D}', '-', $matches[1]); - $index = 2; - } elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) { - $version = $matches[1] - .(!empty($matches[2]) ? $matches[2] : '.0') - .(!empty($matches[3]) ? $matches[3] : '.0') - .(!empty($matches[4]) ? $matches[4] : '.0'); - $index = 5; - } - - // add version modifiers if a version was matched - if (isset($index)) { - if (!empty($matches[$index])) { - if ('stable' === $matches[$index]) { - return $version; - } - $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : ''); - } - - if (!empty($matches[$index + 2])) { - $version .= '-dev'; - } - - return $version; - } - - // match dev branches - if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { - try { - return $this->normalizeBranch($match[1]); - } catch (\Exception $e) { - } - } - - $extraMessage = ''; - if (preg_match('{ +as +'.preg_quote($version).'$}', $fullVersion)) { - $extraMessage = ' in "'.$fullVersion.'", the alias must be an exact version'; - } elseif (preg_match('{^'.preg_quote($version).' +as +}', $fullVersion)) { - $extraMessage = ' in "'.$fullVersion.'", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; - } - - throw new \UnexpectedValueException('Invalid version string "'.$version.'"'.$extraMessage); - } - - /** - * Extract numeric prefix from alias, if it is in numeric format, suitable for - * version comparison - * - * @param string $branch Branch name (e.g. 2.1.x-dev) - * @return string|false Numeric prefix if present (e.g. 2.1.) or false - */ - public function parseNumericAliasPrefix($branch) - { - if (preg_match('/^(?P(\d+\\.)*\d+)(?:\.x)?-dev$/i', $branch, $matches)) { - return $matches['version']."."; - } - - return false; - } - - /** - * Normalizes a branch name to be able to perform comparisons on it - * - * @param string $name - * @return string - */ - public function normalizeBranch($name) - { - $name = trim($name); - - if (in_array($name, array('master', 'trunk', 'default'))) { - return $this->normalize($name); - } - - if (preg_match('#^v?(\d+)(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?$#i', $name, $matches)) { - $version = ''; - for ($i = 1; $i < 5; $i++) { - $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; - } - - return str_replace('x', '9999999', $version).'-dev'; - } - - return 'dev-'.$name; - } - - /** - * @deprecated use ArrayLoader::parseLinks() instead - * @param string $source source package name - * @param string $sourceVersion source package version (pretty version ideally) - * @param string $description link description (e.g. requires, replaces, ..) - * @param array $links array of package name => constraint mappings - * @return Link[] - */ - public function parseLinks($source, $sourceVersion, $description, $links) - { - trigger_error(__METHOD__.' is deprecated. Use '. - '\Composer\Package\Loader\ArrayLoader::parseLinks() instead', E_USER_DEPRECATED); - $loader = new ArrayLoader($this, false); - - return $loader->parseLinks($source, $sourceVersion, $description, $links); - } - - /** - * Parses as constraint string into LinkConstraint objects - * - * @param string $constraints - * @return \Composer\Package\LinkConstraint\LinkConstraintInterface - */ - public function parseConstraints($constraints) - { - $prettyConstraint = $constraints; - - if (preg_match('{^([^,\s]*?)@('.implode('|', self::$stabilities).')$}i', $constraints, $match)) { - $constraints = empty($match[1]) ? '*' : $match[1]; - } - - if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) { - $constraints = $match[1]; - } - - $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints)); - $orGroups = array(); - foreach ($orConstraints as $constraints) { - $andConstraints = preg_split('{(?< ,]) *(? 1) { - $constraintObjects = array(); - foreach ($andConstraints as $constraint) { - foreach ($this->parseConstraint($constraint) as $parsedConstraint) { - $constraintObjects[] = $parsedConstraint; - } - } - } else { - $constraintObjects = $this->parseConstraint($andConstraints[0]); - } - - if (1 === count($constraintObjects)) { - $constraint = $constraintObjects[0]; - } else { - $constraint = new MultiConstraint($constraintObjects); - } - - $orGroups[] = $constraint; - } - - if (1 === count($orGroups)) { - $constraint = $orGroups[0]; - } else { - $constraint = new MultiConstraint($orGroups, false); - } - - $constraint->setPrettyString($prettyConstraint); - - return $constraint; - } - - private function parseConstraint($constraint) - { - if (preg_match('{^([^,\s]+?)@('.implode('|', self::$stabilities).')$}i', $constraint, $match)) { - $constraint = $match[1]; - if ($match[2] !== 'stable') { - $stabilityModifier = $match[2]; - } - } - - if (preg_match('{^[xX*](\.[xX*])*$}i', $constraint)) { - return array(new EmptyConstraint); - } - - $versionRegex = '(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?'.self::$modifierRegex; - - // match tilde constraints - // like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous - // version, to ensure that unstable instances of the current version are allowed. - // however, if a stability suffix is added to the constraint, then a >= match on the current version is - // used instead - if (preg_match('{^~>?'.$versionRegex.'$}i', $constraint, $matches)) { - if (substr($constraint, 0, 2) === '~>') { - throw new \UnexpectedValueException( - 'Could not parse version constraint '.$constraint.': '. - 'Invalid operator "~>", you probably meant to use the "~" operator' - ); - } - - // Work out which position in the version we are operating at - if (isset($matches[4]) && '' !== $matches[4]) { - $position = 4; - } elseif (isset($matches[3]) && '' !== $matches[3]) { - $position = 3; - } elseif (isset($matches[2]) && '' !== $matches[2]) { - $position = 2; - } else { - $position = 1; - } - - // Calculate the stability suffix - $stabilitySuffix = ''; - if (!empty($matches[5])) { - $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : ''); - } - - if (!empty($matches[7])) { - $stabilitySuffix .= '-dev'; - } - - if (!$stabilitySuffix) { - $stabilitySuffix = "-dev"; - } - $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix; - $lowerBound = new VersionConstraint('>=', $lowVersion); - - // For upper bound, we increment the position of one more significance, - // but highPosition = 0 would be illegal - $highPosition = max(1, $position - 1); - $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; - $upperBound = new VersionConstraint('<', $highVersion); - - return array( - $lowerBound, - $upperBound - ); - } - - // 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 - if (preg_match('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?\.[xX*]$}', $constraint, $matches)) { - if (isset($matches[3]) && '' !== $matches[3]) { - $position = 3; - } elseif (isset($matches[2]) && '' !== $matches[2]) { - $position = 2; - } else { - $position = 1; - } - - $lowVersion = $this->manipulateVersionString($matches, $position) . "-dev"; - $highVersion = $this->manipulateVersionString($matches, $position, 1) . "-dev"; - - if ($lowVersion === "0.0.0.0-dev") { - return array(new VersionConstraint('<', $highVersion)); - } - - return array( - new VersionConstraint('>=', $lowVersion), - new VersionConstraint('<', $highVersion), - ); - } - - // match hyphen constraints - if (preg_match('{^(?P'.$versionRegex.') +- +(?P'.$versionRegex.')($)}i', $constraint, $matches)) { - // Calculate the stability suffix - $lowStabilitySuffix = ''; - if (empty($matches[6]) && empty($matches[8])) { - $lowStabilitySuffix = '-dev'; - } - - $lowVersion = $this->normalize($matches['from']); - $lowerBound = new VersionConstraint('>=', $lowVersion . $lowStabilitySuffix); - - $empty = function ($x) { - return ($x === 0 || $x === "0") ? false : empty($x); - }; - - if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) { - $highVersion = $this->normalize($matches['to']); - $upperBound = new VersionConstraint('<=', $highVersion); - } else { - $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]); - $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev'; - $upperBound = new VersionConstraint('<', $highVersion); - } - - return array( - $lowerBound, - $upperBound - ); - } - - // match operators constraints - if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) { - try { - $version = $this->normalize($matches[2]); - - if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') { - $version .= '-' . $stabilityModifier; - } elseif ('<' === $matches[1] || '>=' === $matches[1]) { - if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) { - if (substr($matches[2], 0, 4) !== 'dev-') { - $version .= '-dev'; - } - } - } - - return array(new VersionConstraint($matches[1] ?: '=', $version)); - } catch (\Exception $e) { - } - } - - $message = 'Could not parse version constraint '.$constraint; - if (isset($e)) { - $message .= ': '. $e->getMessage(); - } - - throw new \UnexpectedValueException($message); - } - - /** - * Increment, decrement, or simply pad a version number. - * - * Support function for {@link parseConstraint()} - * - * @param array $matches Array with version parts in array indexes 1,2,3,4 - * @param int $position 1,2,3,4 - which segment of the version to decrement - * @param int $increment - * @param string $pad The string to pad version parts after $position - * @return string The new version - */ - private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') - { - for ($i = 4; $i > 0; $i--) { - if ($i > $position) { - $matches[$i] = $pad; - } elseif ($i == $position && $increment) { - $matches[$i] += $increment; - // If $matches[$i] was 0, carry the decrement - if ($matches[$i] < 0) { - $matches[$i] = $pad; - $position--; - - // Return null on a carry overflow - if ($i == 1) { - return; - } - } - } - } - - return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; - } - - private function expandStability($stability) - { - $stability = strtolower($stability); - - switch ($stability) { - case 'a': - return 'alpha'; - case 'b': - return 'beta'; - case 'p': - case 'pl': - return 'patch'; - case 'rc': - return 'RC'; - default: - return $stability; - } - } - - /** - * Parses a name/version pairs and returns an array of pairs + the - * - * @param array $pairs a set of package/version pairs separated by ":", "=" or " " - * @return array[] array of arrays containing a name and (if provided) a version + * @return array[] */ public function parseNameVersionPairs(array $pairs) { diff --git a/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php b/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php deleted file mode 100644 index 892b7fef7..000000000 --- a/tests/Composer/Test/Package/LinkConstraint/MultiConstraintTest.php +++ /dev/null @@ -1,54 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\LinkConstraint; - -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\LinkConstraint\MultiConstraint; - -class MultiConstraintTest extends \PHPUnit_Framework_TestCase -{ - public function testMultiVersionMatchSucceeds() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvide = new VersionConstraint('==', '1.1'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - - $this->assertTrue($multiRequire->matches($versionProvide)); - } - - public function testMultiVersionProvidedMatchSucceeds() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvideStart = new VersionConstraint('>=', '1.1'); - $versionProvideEnd = new VersionConstraint('<', '2.0'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - $multiProvide = new MultiConstraint(array($versionProvideStart, $versionProvideEnd)); - - $this->assertTrue($multiRequire->matches($multiProvide)); - } - - public function testMultiVersionMatchFails() - { - $versionRequireStart = new VersionConstraint('>', '1.0'); - $versionRequireEnd = new VersionConstraint('<', '1.2'); - $versionProvide = new VersionConstraint('==', '1.2'); - - $multiRequire = new MultiConstraint(array($versionRequireStart, $versionRequireEnd)); - - $this->assertFalse($multiRequire->matches($versionProvide)); - } -} diff --git a/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php b/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php deleted file mode 100644 index e2adda282..000000000 --- a/tests/Composer/Test/Package/LinkConstraint/VersionConstraintTest.php +++ /dev/null @@ -1,105 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\LinkConstraint; - -use Composer\Package\LinkConstraint\VersionConstraint; - -class VersionConstraintTest extends \PHPUnit_Framework_TestCase -{ - public static function successfulVersionMatches() - { - return array( - // require provide - array('==', '1', '==', '1'), - array('>=', '1', '>=', '2'), - array('>=', '2', '>=', '1'), - array('>=', '2', '>', '1'), - array('<=', '2', '>=', '1'), - array('>=', '1', '<=', '2'), - array('==', '2', '>=', '2'), - array('!=', '1', '!=', '1'), - array('!=', '1', '==', '2'), - array('!=', '1', '<', '1'), - array('!=', '1', '<=', '1'), - array('!=', '1', '>', '1'), - array('!=', '1', '>=', '1'), - array('==', 'dev-foo-bar', '==', 'dev-foo-bar'), - array('==', 'dev-foo-xyz', '==', 'dev-foo-xyz'), - array('>=', 'dev-foo-bar', '>=', 'dev-foo-xyz'), - array('<=', 'dev-foo-bar', '<', 'dev-foo-xyz'), - array('!=', 'dev-foo-bar', '<', 'dev-foo-xyz'), - array('>=', 'dev-foo-bar', '!=', 'dev-foo-bar'), - array('!=', 'dev-foo-bar', '!=', 'dev-foo-xyz'), - ); - } - - /** - * @dataProvider successfulVersionMatches - */ - public function testVersionMatchSucceeds($requireOperator, $requireVersion, $provideOperator, $provideVersion) - { - $versionRequire = new VersionConstraint($requireOperator, $requireVersion); - $versionProvide = new VersionConstraint($provideOperator, $provideVersion); - - $this->assertTrue($versionRequire->matches($versionProvide)); - } - - public static function failingVersionMatches() - { - return array( - // require provide - array('==', '1', '==', '2'), - array('>=', '2', '<=', '1'), - array('>=', '2', '<', '2'), - array('<=', '2', '>', '2'), - array('>', '2', '<=', '2'), - array('<=', '1', '>=', '2'), - array('>=', '2', '<=', '1'), - array('==', '2', '<', '2'), - array('!=', '1', '==', '1'), - array('==', '1', '!=', '1'), - array('==', 'dev-foo-dist', '==', 'dev-foo-zist'), - array('==', 'dev-foo-bist', '==', 'dev-foo-aist'), - array('<=', 'dev-foo-bist', '>=', 'dev-foo-aist'), - array('>=', 'dev-foo-bist', '<', 'dev-foo-aist'), - array('<', '0.12', '==', 'dev-foo'), // branches are not comparable - array('>', '0.12', '==', 'dev-foo'), // branches are not comparable - ); - } - - /** - * @dataProvider failingVersionMatches - */ - public function testVersionMatchFails($requireOperator, $requireVersion, $provideOperator, $provideVersion) - { - $versionRequire = new VersionConstraint($requireOperator, $requireVersion); - $versionProvide = new VersionConstraint($provideOperator, $provideVersion); - - $this->assertFalse($versionRequire->matches($versionProvide)); - } - - public function testComparableBranches() - { - $versionRequire = new VersionConstraint('>', '0.12'); - $versionProvide = new VersionConstraint('==', 'dev-foo'); - - $this->assertFalse($versionRequire->matches($versionProvide)); - $this->assertFalse($versionRequire->matchSpecific($versionProvide, true)); - - $versionRequire = new VersionConstraint('<', '0.12'); - $versionProvide = new VersionConstraint('==', 'dev-foo'); - - $this->assertFalse($versionRequire->matches($versionProvide)); - $this->assertTrue($versionRequire->matchSpecific($versionProvide, true)); - } -} diff --git a/tests/Composer/Test/Package/Version/VersionParserTest.php b/tests/Composer/Test/Package/Version/VersionParserTest.php deleted file mode 100644 index fe2dab749..000000000 --- a/tests/Composer/Test/Package/Version/VersionParserTest.php +++ /dev/null @@ -1,472 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\Version; - -use Composer\Package\Link; -use Composer\Package\Version\VersionParser; -use Composer\Package\LinkConstraint\MultiConstraint; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Package\LinkConstraint\EmptyConstraint; -use Composer\Package\PackageInterface; - -class VersionParserTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @dataProvider numericAliasVersions - */ - public function testParseNumericAliasPrefix($input, $expected) - { - $parser = new VersionParser; - $this->assertSame($expected, $parser->parseNumericAliasPrefix($input)); - } - - public function numericAliasVersions() - { - return array( - array('0.x-dev', '0.'), - array('1.0.x-dev', '1.0.'), - array('1.x-dev', '1.'), - array('1.2.x-dev', '1.2.'), - array('1.2-dev', '1.2.'), - array('1-dev', '1.'), - array('dev-develop', false), - array('dev-master', false), - ); - } - - /** - * @dataProvider successfulNormalizedVersions - */ - public function testNormalizeSucceeds($input, $expected) - { - $parser = new VersionParser; - $this->assertSame($expected, $parser->normalize($input)); - } - - public function successfulNormalizedVersions() - { - return array( - 'none' => array('1.0.0', '1.0.0.0'), - 'none/2' => array('1.2.3.4', '1.2.3.4'), - 'parses state' => array('1.0.0RC1dev', '1.0.0.0-RC1-dev'), - 'CI parsing' => array('1.0.0-rC15-dev', '1.0.0.0-RC15-dev'), - 'delimiters' => array('1.0.0.RC.15-dev', '1.0.0.0-RC15-dev'), - 'RC uppercase' => array('1.0.0-rc1', '1.0.0.0-RC1'), - 'patch replace' => array('1.0.0.pl3-dev', '1.0.0.0-patch3-dev'), - 'forces w.x.y.z' => array('1.0-dev', '1.0.0.0-dev'), - 'forces w.x.y.z/2' => array('0', '0.0.0.0'), - 'parses long' => array('10.4.13-beta', '10.4.13.0-beta'), - 'parses long/2' => array('10.4.13beta2', '10.4.13.0-beta2'), - 'parses long/semver' => array('10.4.13beta.2', '10.4.13.0-beta2'), - 'expand shorthand' => array('10.4.13-b', '10.4.13.0-beta'), - 'expand shorthand2' => array('10.4.13-b5', '10.4.13.0-beta5'), - 'strips leading v' => array('v1.0.0', '1.0.0.0'), - 'strips v/datetime' => array('v20100102', '20100102'), - 'parses dates y-m' => array('2010.01', '2010-01'), - 'parses dates w/ .' => array('2010.01.02', '2010-01-02'), - 'parses dates w/ -' => array('2010-01-02', '2010-01-02'), - 'parses numbers' => array('2010-01-02.5', '2010-01-02-5'), - 'parses dates y.m.Y' => array('2010.1.555', '2010.1.555.0'), - 'parses datetime' => array('20100102-203040', '20100102-203040'), - 'parses dt+number' => array('20100102203040-10', '20100102203040-10'), - 'parses dt+patch' => array('20100102-203040-p1', '20100102-203040-patch1'), - 'parses master' => array('dev-master', '9999999-dev'), - 'parses trunk' => array('dev-trunk', '9999999-dev'), - 'parses branches' => array('1.x-dev', '1.9999999.9999999.9999999-dev'), - 'parses arbitrary' => array('dev-feature-foo', 'dev-feature-foo'), - 'parses arbitrary2' => array('DEV-FOOBAR', 'dev-FOOBAR'), - 'parses arbitrary3' => array('dev-feature/foo', 'dev-feature/foo'), - 'ignores aliases' => array('dev-master as 1.0.0', '9999999-dev'), - 'semver metadata' => array('dev-master+foo.bar', '9999999-dev'), - 'semver metadata/2' => array('1.0.0-beta.5+foo', '1.0.0.0-beta5'), - 'semver metadata/3' => array('1.0.0+foo', '1.0.0.0'), - 'metadata w/ alias' => array('1.0.0+foo as 2.0', '1.0.0.0'), - ); - } - - /** - * @dataProvider failingNormalizedVersions - * @expectedException UnexpectedValueException - */ - public function testNormalizeFails($input) - { - $parser = new VersionParser; - $parser->normalize($input); - } - - public function failingNormalizedVersions() - { - return array( - 'empty ' => array(''), - 'invalid chars' => array('a'), - 'invalid type' => array('1.0.0-meh'), - 'too many bits' => array('1.0.0.0.0'), - 'non-dev arbitrary' => array('feature-foo'), - 'metadata w/ space' => array('1.0.0+foo bar'), - ); - } - - /** - * @dataProvider successfulNormalizedBranches - */ - public function testNormalizeBranch($input, $expected) - { - $parser = new VersionParser; - $this->assertSame((string) $expected, (string) $parser->normalizeBranch($input)); - } - - public function successfulNormalizedBranches() - { - return array( - 'parses x' => array('v1.x', '1.9999999.9999999.9999999-dev'), - 'parses *' => array('v1.*', '1.9999999.9999999.9999999-dev'), - 'parses digits' => array('v1.0', '1.0.9999999.9999999-dev'), - 'parses digits/2' => array('2.0', '2.0.9999999.9999999-dev'), - 'parses long x' => array('v1.0.x', '1.0.9999999.9999999-dev'), - 'parses long *' => array('v1.0.3.*', '1.0.3.9999999-dev'), - 'parses long digits' => array('v2.4.0', '2.4.0.9999999-dev'), - 'parses long digits/2' => array('2.4.4', '2.4.4.9999999-dev'), - 'parses master' => array('master', '9999999-dev'), - 'parses trunk' => array('trunk', '9999999-dev'), - 'parses arbitrary' => array('feature-a', 'dev-feature-a'), - 'parses arbitrary/2' => array('FOOBAR', 'dev-FOOBAR'), - ); - } - - public function testParseConstraintsIgnoresStabilityFlag() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0@dev')); - } - - public function testParseConstraintsIgnoresReferenceOnDevVersion() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.9999999.9999999-dev'), (string) $parser->parseConstraints('1.0.x-dev#abcd123')); - $this->assertSame((string) new VersionConstraint('=', '1.0.9999999.9999999-dev'), (string) $parser->parseConstraints('1.0.x-dev#trunk/@123')); - } - - /** - * @expectedException UnexpectedValueException - */ - public function testParseConstraintsFailsOnBadReference() - { - $parser = new VersionParser; - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0#abcd123')); - $this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0#trunk/@123')); - } - - /** - * @expectedException UnexpectedValueException - * @expectedExceptionMessage Invalid operator "~>", you probably meant to use the "~" operator - */ - public function testParseConstraintsNudgesRubyDevsTowardsThePathOfRighteousness() - { - $parser = new VersionParser; - $parser->parseConstraints('~>1.2'); - } - - /** - * @dataProvider simpleConstraints - */ - public function testParseConstraintsSimple($input, $expected) - { - $parser = new VersionParser; - $this->assertSame((string) $expected, (string) $parser->parseConstraints($input)); - } - - public function simpleConstraints() - { - return array( - 'match any' => array('*', new EmptyConstraint()), - 'match any/2' => array('*.*', new EmptyConstraint()), - 'match any/3' => array('*.x.*', new EmptyConstraint()), - 'match any/4' => array('x.X.x.*', new EmptyConstraint()), - 'not equal' => array('<>1.0.0', new VersionConstraint('<>', '1.0.0.0')), - 'not equal/2' => array('!=1.0.0', new VersionConstraint('!=', '1.0.0.0')), - 'greater than' => array('>1.0.0', new VersionConstraint('>', '1.0.0.0')), - 'lesser than' => array('<1.2.3.4', new VersionConstraint('<', '1.2.3.4-dev')), - 'less/eq than' => array('<=1.2.3', new VersionConstraint('<=', '1.2.3.0')), - 'great/eq than' => array('>=1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), - 'equals' => array('=1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'double equals' => array('==1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'no op means eq' => array('1.2.3', new VersionConstraint('=', '1.2.3.0')), - 'completes version' => array('=1.0', new VersionConstraint('=', '1.0.0.0')), - 'shorthand beta' => array('1.2.3b5', new VersionConstraint('=', '1.2.3.0-beta5')), - 'accepts spaces' => array('>= 1.2.3', new VersionConstraint('>=', '1.2.3.0-dev')), - 'accepts spaces/2' => array('< 1.2.3', new VersionConstraint('<', '1.2.3.0-dev')), - 'accepts spaces/3' => array('> 1.2.3', new VersionConstraint('>', '1.2.3.0')), - 'accepts master' => array('>=dev-master', new VersionConstraint('>=', '9999999-dev')), - 'accepts master/2' => array('dev-master', new VersionConstraint('=', '9999999-dev')), - 'accepts arbitrary' => array('dev-feature-a', new VersionConstraint('=', 'dev-feature-a')), - 'regression #550' => array('dev-some-fix', new VersionConstraint('=', 'dev-some-fix')), - 'regression #935' => array('dev-CAPS', new VersionConstraint('=', 'dev-CAPS')), - 'ignores aliases' => array('dev-master as 1.0.0', new VersionConstraint('=', '9999999-dev')), - 'lesser than override' => array('<1.2.3.4-stable', new VersionConstraint('<', '1.2.3.4')), - 'great/eq than override' => array('>=1.2.3.4-stable', new VersionConstraint('>=', '1.2.3.4')), - ); - } - - /** - * @dataProvider wildcardConstraints - */ - public function testParseConstraintsWildcard($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 wildcardConstraints() - { - return array( - array('2.*', new VersionConstraint('>=', '2.0.0.0-dev'), new VersionConstraint('<', '3.0.0.0-dev')), - array('20.*', new VersionConstraint('>=', '20.0.0.0-dev'), new VersionConstraint('<', '21.0.0.0-dev')), - array('2.0.*', new VersionConstraint('>=', '2.0.0.0-dev'), new VersionConstraint('<', '2.1.0.0-dev')), - array('2.2.x', new VersionConstraint('>=', '2.2.0.0-dev'), new VersionConstraint('<', '2.3.0.0-dev')), - array('2.10.X', new VersionConstraint('>=', '2.10.0.0-dev'), new VersionConstraint('<', '2.11.0.0-dev')), - array('2.1.3.*', new VersionConstraint('>=', '2.1.3.0-dev'), new VersionConstraint('<', '2.1.4.0-dev')), - array('0.*', null, new VersionConstraint('<', '1.0.0.0-dev')), - ); - } - - /** - * @dataProvider tildeConstraints - */ - public function testParseTildeWildcard($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 tildeConstraints() - { - return array( - array('~1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.0.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '1.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', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<', '1.3.0.0-dev')), - array('~1.2.3.4', new VersionConstraint('>=', '1.2.3.4-dev'), new VersionConstraint('<', '1.2.4.0-dev')), - array('~1.2-beta',new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2-b2', new VersionConstraint('>=', '1.2.0.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2-BETA2', new VersionConstraint('>=', '1.2.0.0-beta2'), new VersionConstraint('<', '2.0.0.0-dev')), - array('~1.2.2-dev', new VersionConstraint('>=', '1.2.2.0-dev'), new VersionConstraint('<', '1.3.0.0-dev')), - array('~1.2.2-stable', new VersionConstraint('>=', '1.2.2.0-stable'), new VersionConstraint('<', '1.3.0.0-dev')), - ); - } - - /** - * @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.2.0', 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 - */ - public function testParseHyphen($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 hyphenConstraints() - { - return array( - array('1 - 2', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '3.0.0.0-dev')), - array('1.2.3 - 2.3.4.5', new VersionConstraint('>=', '1.2.3.0-dev'), new VersionConstraint('<=', '2.3.4.5')), - array('1.2-beta - 2.3', new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<', '2.4.0.0-dev')), - array('1.2-beta - 2.3-dev', new VersionConstraint('>=', '1.2.0.0-beta'), new VersionConstraint('<=', '2.3.0.0-dev')), - array('1.2-RC - 2.3.1', new VersionConstraint('>=', '1.2.0.0-RC'), new VersionConstraint('<=', '2.3.1.0')), - array('1.2.3-alpha - 2.3-RC', new VersionConstraint('>=', '1.2.3.0-alpha'), new VersionConstraint('<=', '2.3.0.0-RC')), - array('1 - 2.0', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.1.0.0-dev')), - array('1 - 2.1', new VersionConstraint('>=', '1.0.0.0-dev'), new VersionConstraint('<', '2.2.0.0-dev')), - array('1.2 - 2.1.0', new VersionConstraint('>=', '1.2.0.0-dev'), new VersionConstraint('<=', '2.1.0.0')), - array('1.3 - 2.1.3', new VersionConstraint('>=', '1.3.0.0-dev'), new VersionConstraint('<=', '2.1.3.0')), - ); - } - - /** - * @dataProvider multiConstraintProvider - */ - public function testParseConstraintsMulti($constraint) - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<=', '3.0.0.0'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints($constraint)); - } - - public function multiConstraintProvider() - { - return array( - array('>2.0,<=3.0'), - array('>2.0 <=3.0'), - array('>2.0 <=3.0'), - array('>2.0, <=3.0'), - array('>2.0 ,<=3.0'), - array('>2.0 , <=3.0'), - array('>2.0 , <=3.0'), - array('> 2.0 <= 3.0'), - array('> 2.0 , <= 3.0'), - array(' > 2.0 , <= 3.0 '), - ); - } - - public function testParseConstraintsMultiWithStabilitySuffix() - { - $parser = new VersionParser; - $first = new VersionConstraint('>=', '1.1.0.0-alpha4'); - $second = new VersionConstraint('<', '1.2.9999999.9999999-dev'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>=1.1.0-alpha4,<1.2.x-dev')); - - $first = new VersionConstraint('>=', '1.1.0.0-alpha4'); - $second = new VersionConstraint('<', '1.2.0.0-beta2'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>=1.1.0-alpha4,<1.2-beta2')); - } - - /** - * @dataProvider multiConstraintProvider2 - */ - public function testParseConstraintsMultiDisjunctiveHasPrioOverConjuctive($constraint) - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<', '2.0.5.0-dev'); - $third = new VersionConstraint('>', '2.0.6.0'); - $multi1 = new MultiConstraint(array($first, $second)); - $multi2 = new MultiConstraint(array($multi1, $third), false); - $this->assertSame((string) $multi2, (string) $parser->parseConstraints($constraint)); - } - - public function multiConstraintProvider2() - { - return array( - array('>2.0,<2.0.5 | >2.0.6'), - array('>2.0,<2.0.5 || >2.0.6'), - array('> 2.0 , <2.0.5 | > 2.0.6'), - ); - } - - public function testParseConstraintsMultiWithStabilities() - { - $parser = new VersionParser; - $first = new VersionConstraint('>', '2.0.0.0'); - $second = new VersionConstraint('<=', '3.0.0.0-dev'); - $multi = new MultiConstraint(array($first, $second)); - $this->assertSame((string) $multi, (string) $parser->parseConstraints('>2.0@stable,<=3.0@dev')); - } - - /** - * @dataProvider failingConstraints - * @expectedException UnexpectedValueException - */ - public function testParseConstraintsFails($input) - { - $parser = new VersionParser; - $parser->parseConstraints($input); - } - - public function failingConstraints() - { - return array( - 'empty ' => array(''), - 'invalid version' => array('1.0.0-meh'), - 'operator abuse' => array('>2.0,,<=3.0'), - 'operator abuse/2' => array('>2.0 ,, <=3.0'), - 'operator abuse/3' => array('>2.0 ||| <=3.0'), - ); - } - - /** - * @dataProvider stabilityProvider - */ - public function testParseStability($expected, $version) - { - $this->assertSame($expected, VersionParser::parseStability($version)); - } - - public function stabilityProvider() - { - return array( - array('stable', '1'), - array('stable', '1.0'), - array('stable', '3.2.1'), - array('stable', 'v3.2.1'), - array('dev', 'v2.0.x-dev'), - array('dev', 'v2.0.x-dev#abc123'), - array('dev', 'v2.0.x-dev#trunk/@123'), - array('RC', '3.0-RC2'), - array('dev', 'dev-master'), - array('dev', '3.1.2-dev'), - array('stable', '3.1.2-pl2'), - array('stable', '3.1.2-patch'), - array('alpha', '3.1.2-alpha5'), - array('beta', '3.1.2-beta'), - array('beta', '2.0B1'), - array('alpha', '1.2.0a1'), - array('alpha', '1.2_a1'), - array('RC', '2.0.0rc1') - ); - } -}