Legoktm has uploaded a new change for review.
https://gerrit.wikimedia.org/r/228132
Change subject: Add composer/semver 0.1.0
......................................................................
Add composer/semver 0.1.0
Will be used in MediaWiki core I778582721.
Bug: T99086
Change-Id: I50d636df321b6aa7a921c8ca1d111f5b0c459ca9
---
M composer.json
M composer.lock
M composer/autoload_classmap.php
M composer/autoload_psr4.php
M composer/installed.json
A composer/semver/CHANGELOG.md
A composer/semver/LICENSE
A composer/semver/README.md
A composer/semver/composer.json
A composer/semver/src/Comparator.php
A composer/semver/src/Constraint/EmptyConstraint.php
A composer/semver/src/Constraint/LinkConstraintInterface.php
A composer/semver/src/Constraint/MultiConstraint.php
A composer/semver/src/Constraint/SpecificConstraint.php
A composer/semver/src/Constraint/VersionConstraint.php
A composer/semver/src/VersionParser.php
16 files changed, 1,335 insertions(+), 1 deletion(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/vendor
refs/changes/32/228132/1
diff --git a/composer.json b/composer.json
index 0e55797..e3884d1 100644
--- a/composer.json
+++ b/composer.json
@@ -9,6 +9,7 @@
},
"prefer-stable": true,
"require": {
+ "composer/semver": "0.1.0",
"cssjanus/cssjanus": "1.1.1",
"kzykhys/pygments": "1.0",
"leafo/lessphp": "0.5.0",
diff --git a/composer.lock b/composer.lock
index 2f77679..792fa6a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,9 +4,70 @@
"Read more about it at
https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "09e6099a2d48fd0aa20ad2fb526eedcd",
+ "hash": "5fe0e654588289e1b4b522428039ace3",
"packages": [
{
+ "name": "composer/semver",
+ "version": "0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "f6469477aa1952f2fcbd0ab52fcc7662f1dd0173"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/composer/semver/zipball/f6469477aa1952f2fcbd0ab52fcc7662f1dd0173",
+ "reference": "f6469477aa1952f2fcbd0ab52fcc7662f1dd0173",
+ "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": "[email protected]"
+ },
+ {
+ "name": "Nils Adermann",
+ "email": "[email protected]",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "[email protected]",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Semver library that offers utilities, version
constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "time": "2015-07-23 06:21:50"
+ },
+ {
"name": "cssjanus/cssjanus",
"version": "v1.1.1",
"source": {
diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php
index a8d8445..86f69e8 100644
--- a/composer/autoload_classmap.php
+++ b/composer/autoload_classmap.php
@@ -16,6 +16,13 @@
'Cdb\\Writer' => $vendorDir . '/wikimedia/cdb/src/Writer.php',
'Cdb\\Writer\\DBA' => $vendorDir . '/wikimedia/cdb/src/Writer/DBA.php',
'Cdb\\Writer\\PHP' => $vendorDir . '/wikimedia/cdb/src/Writer/PHP.php',
+ 'Composer\\Semver\\Comparator' => $vendorDir .
'/composer/semver/src/Comparator.php',
+ 'Composer\\Semver\\Constraint\\EmptyConstraint' => $vendorDir .
'/composer/semver/src/Constraint/EmptyConstraint.php',
+ 'Composer\\Semver\\Constraint\\LinkConstraintInterface' => $vendorDir .
'/composer/semver/src/Constraint/LinkConstraintInterface.php',
+ 'Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir .
'/composer/semver/src/Constraint/MultiConstraint.php',
+ 'Composer\\Semver\\Constraint\\SpecificConstraint' => $vendorDir .
'/composer/semver/src/Constraint/SpecificConstraint.php',
+ 'Composer\\Semver\\Constraint\\VersionConstraint' => $vendorDir .
'/composer/semver/src/Constraint/VersionConstraint.php',
+ 'Composer\\Semver\\VersionParser' => $vendorDir .
'/composer/semver/src/VersionParser.php',
'Elastica\\AbstractUpdateAction' => $vendorDir .
'/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php',
'Elastica\\Aggregation\\AbstractAggregation' => $vendorDir .
'/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php',
'Elastica\\Aggregation\\AbstractSimpleAggregation' => $vendorDir .
'/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php',
diff --git a/composer/autoload_psr4.php b/composer/autoload_psr4.php
index c9e9ce3..5f09085 100644
--- a/composer/autoload_psr4.php
+++ b/composer/autoload_psr4.php
@@ -11,4 +11,5 @@
'Wikimedia\\Assert\\' => array($vendorDir . '/wikimedia/assert/src'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
+ 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
);
diff --git a/composer/installed.json b/composer/installed.json
index af15ce8..9156f50 100644
--- a/composer/installed.json
+++ b/composer/installed.json
@@ -760,5 +760,68 @@
],
"description": "Provides library of common widgets, layouts, and
windows.",
"homepage": "https://www.mediawiki.org/wiki/OOjs_UI"
+ },
+ {
+ "name": "composer/semver",
+ "version": "0.1.0",
+ "version_normalized": "0.1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "f6469477aa1952f2fcbd0ab52fcc7662f1dd0173"
+ },
+ "dist": {
+ "type": "zip",
+ "url":
"https://api.github.com/repos/composer/semver/zipball/f6469477aa1952f2fcbd0ab52fcc7662f1dd0173",
+ "reference": "f6469477aa1952f2fcbd0ab52fcc7662f1dd0173",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5",
+ "phpunit/phpunit-mock-objects": "~2.3"
+ },
+ "time": "2015-07-23 06:21:50",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Rob Bast",
+ "email": "[email protected]"
+ },
+ {
+ "name": "Nils Adermann",
+ "email": "[email protected]",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "[email protected]",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Semver library that offers utilities, version
constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ]
}
]
diff --git a/composer/semver/CHANGELOG.md b/composer/semver/CHANGELOG.md
new file mode 100644
index 0000000..37d29de
--- /dev/null
+++ b/composer/semver/CHANGELOG.md
@@ -0,0 +1,16 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+### [0.1.0] 2015-07-23
+
+ * Added: `Composer\Semver\Comparator`, various methods to compare versions.
+ * Added: various documents such as README.md, LICENSE, etc.
+ * Added: configuration files for Git, Travis, php-cs-fixer, phpunit.
+ * Break: the following namespaces were renamed:
+ - Namespace: `Composer\Package\Version` -> `Composer\Semver`
+ - Namespace: `Composer\Package\LinkConstraint` ->
`Composer\Semver\Constraint`
+ - Namespace: `Composer\Test\Package\Version` -> `Composer\Test\Semver`
+ - Namespace: `Composer\Test\Package\LinkConstraint` ->
`Composer\Test\Semver\Constraint`
+ * Changed: code style using php-cs-fixer.
diff --git a/composer/semver/LICENSE b/composer/semver/LICENSE
new file mode 100644
index 0000000..4669758
--- /dev/null
+++ b/composer/semver/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2015 Composer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/composer/semver/README.md b/composer/semver/README.md
new file mode 100644
index 0000000..c0b34ce
--- /dev/null
+++ b/composer/semver/README.md
@@ -0,0 +1,50 @@
+composer/semver
+===============
+
+Semver library that offers utilities, version constraint parsing and
validation.
+
+Originally written as part of
[composer/composer](https://github.com/composer/composer),
+now extracted and made available as a stand-alone library.
+
+[](https://travis-ci.org/composer/semver)
+
+Installation
+------------
+
+Install the latest version with:
+
+```bash
+$ composer require composer/semver
+```
+
+Requirements
+------------
+
+* PHP 5.3.2 is required but using the latest version of PHP is highly
recommended.
+
+Basic usage
+-----------
+
+The `Composer\Semver\Comparator` class provides the following high-level
+functions for comparing versions:
+
+* greaterThan
+* greaterThanOrEqualTo
+* lessThan
+* lessThanOrEqualTo
+* equalTo
+* notEqualTo
+
+Each function takes two version strings as arguments. For example:
+
+```php
+use Composer\Semver\Comparator;
+
+Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0
+```
+
+
+License
+-------
+
+composer/semver is licensed under the MIT License, see the LICENSE file for
details.
diff --git a/composer/semver/composer.json b/composer/semver/composer.json
new file mode 100644
index 0000000..b996186
--- /dev/null
+++ b/composer/semver/composer.json
@@ -0,0 +1,57 @@
+{
+ "name": "composer/semver",
+ "description": "Semver library that offers utilities, version constraint
parsing and validation.",
+ "type": "library",
+ "license": "MIT",
+ "keywords": [
+ "semver",
+ "semantic",
+ "versioning",
+ "validation"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "[email protected]",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "[email protected]",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "[email protected]"
+ }
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/semver/issues"
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5",
+ "phpunit/phpunit-mock-objects": "~2.3"
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Composer\\Semver\\Test\\": "tests"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1-dev"
+ }
+ },
+ "scripts": {
+ "test": "phpunit"
+ }
+}
diff --git a/composer/semver/src/Comparator.php
b/composer/semver/src/Comparator.php
new file mode 100644
index 0000000..8afce22
--- /dev/null
+++ b/composer/semver/src/Comparator.php
@@ -0,0 +1,121 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver;
+
+use Composer\Semver\Constraint\VersionConstraint;
+
+class Comparator
+{
+ /**
+ * Whether $version1 > $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function greaterThan($version1, $version2)
+ {
+ return self::compare($version1, '>', $version2);
+ }
+
+ /**
+ * Whether $version1 >= $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function greaterThanOrEqualTo($version1, $version2)
+ {
+ return self::compare($version1, '>=', $version2);
+ }
+
+ /**
+ * Whether $version1 < $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function lessThan($version1, $version2)
+ {
+ return self::compare($version1, '<', $version2);
+ }
+
+ /**
+ * Whether $version1 <= $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function lessThanOrEqualTo($version1, $version2)
+ {
+ return self::compare($version1, '<=', $version2);
+ }
+
+ /**
+ * Whether $version1 == $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function equalTo($version1, $version2)
+ {
+ return self::compare($version1, '==', $version2);
+ }
+
+ /**
+ * Whether $version1 != $version2.
+ *
+ * @param string $version1
+ * @param string $version2
+ *
+ * @return bool
+ */
+ public static function notEqualTo($version1, $version2)
+ {
+ return self::compare($version1, '!=', $version2);
+ }
+
+ /**
+ * Evaluate $version1 $operator $version2.
+ *
+ * @param string $version1
+ * @param string $operator Comparison operator like ">" or "<=", etc.
+ * @param string $version2
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return bool
+ */
+ public static function compare($version1, $operator, $version2)
+ {
+ if (!in_array($operator, VersionConstraint::getSupportedOperators())) {
+ throw new \InvalidArgumentException(sprintf(
+ 'Operator "%s" not supported, expected one of: %s',
+ $operator,
+ implode(', ', VersionConstraint::getSupportedOperators())
+ ));
+ }
+
+ $constraint = new VersionConstraint($operator, $version2);
+
+ return $constraint->matches(new VersionConstraint('==', $version1));
+ }
+}
diff --git a/composer/semver/src/Constraint/EmptyConstraint.php
b/composer/semver/src/Constraint/EmptyConstraint.php
new file mode 100644
index 0000000..f906030
--- /dev/null
+++ b/composer/semver/src/Constraint/EmptyConstraint.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver\Constraint;
+
+/**
+ * Defines an absence of constraints.
+ *
+ * @author Jordi Boggiano <[email protected]>
+ */
+class EmptyConstraint implements LinkConstraintInterface
+{
+ /** @var string */
+ protected $prettyString;
+
+ /**
+ * @param LinkConstraintInterface $provider
+ *
+ * @return bool
+ */
+ public function matches(LinkConstraintInterface $provider)
+ {
+ return true;
+ }
+
+ /**
+ * @param $prettyString
+ */
+ public function setPrettyString($prettyString)
+ {
+ $this->prettyString = $prettyString;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPrettyString()
+ {
+ if ($this->prettyString) {
+ return $this->prettyString;
+ }
+
+ return $this->__toString();
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return '[]';
+ }
+}
diff --git a/composer/semver/src/Constraint/LinkConstraintInterface.php
b/composer/semver/src/Constraint/LinkConstraintInterface.php
new file mode 100644
index 0000000..21f3421
--- /dev/null
+++ b/composer/semver/src/Constraint/LinkConstraintInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver\Constraint;
+
+/**
+ * Defines a constraint on a link between two packages.
+ *
+ * @author Nils Adermann <[email protected]>
+ */
+interface LinkConstraintInterface
+{
+ public function matches(LinkConstraintInterface $provider);
+
+ public function setPrettyString($prettyString);
+
+ public function getPrettyString();
+
+ public function __toString();
+}
diff --git a/composer/semver/src/Constraint/MultiConstraint.php
b/composer/semver/src/Constraint/MultiConstraint.php
new file mode 100644
index 0000000..a688439
--- /dev/null
+++ b/composer/semver/src/Constraint/MultiConstraint.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver\Constraint;
+
+/**
+ * Defines a conjunctive or disjunctive set of constraints on the target of a
package link.
+ *
+ * @author Nils Adermann <[email protected]>
+ * @author Jordi Boggiano <[email protected]>
+ */
+class MultiConstraint implements LinkConstraintInterface
+{
+ /** @var array */
+ protected $constraints;
+
+ /** @var string */
+ protected $prettyString;
+
+ /** @var bool */
+ 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;
+ }
+
+ /**
+ * @param LinkConstraintInterface $provider
+ *
+ * @return bool
+ */
+ 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;
+ }
+
+ /**
+ * @param string $prettyString
+ */
+ public function setPrettyString($prettyString)
+ {
+ $this->prettyString = $prettyString;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPrettyString()
+ {
+ if ($this->prettyString) {
+ return $this->prettyString;
+ }
+
+ return $this->__toString();
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ $constraints = array();
+ foreach ($this->constraints as $constraint) {
+ $constraints[] = $constraint->__toString();
+ }
+
+ return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints)
. ']';
+ }
+}
diff --git a/composer/semver/src/Constraint/SpecificConstraint.php
b/composer/semver/src/Constraint/SpecificConstraint.php
new file mode 100644
index 0000000..334dd1f
--- /dev/null
+++ b/composer/semver/src/Constraint/SpecificConstraint.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver\Constraint;
+
+/**
+ * Provides a common basis for specific package link constraints.
+ *
+ * @author Nils Adermann <[email protected]>
+ */
+abstract class SpecificConstraint implements LinkConstraintInterface
+{
+ /** @var string */
+ protected $prettyString;
+
+ /**
+ * @param LinkConstraintInterface $provider
+ *
+ * @return bool
+ */
+ public function matches(LinkConstraintInterface $provider)
+ {
+ if ($provider instanceof MultiConstraint) {
+ // turn matching around to find a match
+ return $provider->matches($this);
+ } elseif ($provider instanceof $this) {
+ // see note at bottom of this class declaration
+ return $this->matchSpecific($provider);
+ }
+
+ return true;
+ }
+
+ /**
+ * @param string $prettyString
+ */
+ public function setPrettyString($prettyString)
+ {
+ $this->prettyString = $prettyString;
+ }
+
+ /**
+ * @return string
+ */
+ 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(<SpecificConstraintType> $provider);
+}
diff --git a/composer/semver/src/Constraint/VersionConstraint.php
b/composer/semver/src/Constraint/VersionConstraint.php
new file mode 100644
index 0000000..94f5b5e
--- /dev/null
+++ b/composer/semver/src/Constraint/VersionConstraint.php
@@ -0,0 +1,150 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver\Constraint;
+
+/**
+ * Constrains a package link based on package version.
+ *
+ * Version numbers must be compatible with version_compare
+ *
+ * @author Nils Adermann <[email protected]>
+ */
+class VersionConstraint extends SpecificConstraint
+{
+ 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;
+
+ /**
+ * Get all supported comparison operators.
+ *
+ * @return array
+ */
+ public static function getSupportedOperators()
+ {
+ return array_keys(self::$transOpStr);
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * @param string $a
+ * @param string $b
+ * @param string $operator
+ * @param bool|false $compareBranches
+ *
+ * @return bool|mixed
+ */
+ 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;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return self::$transOpInt[$this->operator] . ' ' . $this->version;
+ }
+}
diff --git a/composer/semver/src/VersionParser.php
b/composer/semver/src/VersionParser.php
new file mode 100644
index 0000000..f70d2c3
--- /dev/null
+++ b/composer/semver/src/VersionParser.php
@@ -0,0 +1,533 @@
+<?php
+
+/*
+ * This file is part of composer/semver.
+ *
+ * (c) Composer <https://github.com/composer>
+ *
+ * For the full copyright and license information, please view
+ * the LICENSE file that was distributed with this source code.
+ */
+
+namespace Composer\Semver;
+
+use Composer\Semver\Constraint\EmptyConstraint;
+use Composer\Semver\Constraint\LinkConstraintInterface;
+use Composer\Semver\Constraint\MultiConstraint;
+use Composer\Semver\Constraint\VersionConstraint;
+
+/**
+ * Version parser.
+ *
+ * @author Jordi Boggiano <[email protected]>
+ */
+class VersionParser
+{
+ /** @var string */
+ private static $modifierRegex =
'[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
+
+ /** @var array */
+ private static $stabilities = array(
+ 'stable', 'RC', 'beta', 'alpha', 'dev',
+ );
+
+ /**
+ * Returns the stability of a version.
+ *
+ * @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';
+ }
+
+ /**
+ * @param string $stability
+ *
+ * @return string
+ */
+ public static function normalizeStability($stability)
+ {
+ $stability = strtolower($stability);
+
+ return $stability === 'rc' ? 'RC' : $stability;
+ }
+
+ /**
+ * 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<version>(\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;
+ }
+
+ /**
+ * Parses as constraint string into LinkConstraint objects.
+ *
+ * @param string $constraints
+ *
+ * @return 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('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-)
*(?!,|as|$)}', $constraints);
+ if (count($andConstraints) > 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;
+ }
+
+ /**
+ * @param string $constraint
+ *
+ * @return array
+ */
+ 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<from>' . $versionRegex . ') +- +(?P<to>' .
$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.
+ *
+ * @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
+ */
+ public function parseNameVersionPairs(array $pairs)
+ {
+ $pairs = array_values($pairs);
+ $result = array();
+
+ for ($i = 0, $count = count($pairs); $i < $count; ++$i) {
+ $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2',
trim($pairs[$i]));
+ if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false
=== strpos($pairs[$i + 1], '/')) {
+ $pair .= ' ' . $pairs[$i + 1];
+ ++$i;
+ }
+
+ if (strpos($pair, ' ')) {
+ list($name, $version) = explode(' ', $pair, 2);
+ $result[] = array('name' => $name, 'version' => $version);
+ } else {
+ $result[] = array('name' => $pair);
+ }
+ }
+
+ return $result;
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/228132
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I50d636df321b6aa7a921c8ca1d111f5b0c459ca9
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/vendor
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits