1
0
Fork 0

Add wildcard support to ignore-platform-req, fixes #10045 (#10083)

pull/9261/head
Martin Herndl 2021-11-11 15:56:38 +01:00 committed by GitHub
parent 8542321a31
commit 7eca450d9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 180 additions and 16 deletions

View File

@ -117,7 +117,7 @@ resolution.
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement(`php`, * **--ignore-platform-req:** ignore a specific platform requirement(`php`,
`hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
does not fulfill it. does not fulfill it. Multiple requirements can be ignored via wildcard.
## update / u ## update / u
@ -202,7 +202,7 @@ php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement(`php`, * **--ignore-platform-req:** ignore a specific platform requirement(`php`,
`hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
does not fulfill it. does not fulfill it. Multiple requirements can be ignored via wildcard.
* **--prefer-stable:** Prefer stable versions of dependencies. * **--prefer-stable:** Prefer stable versions of dependencies.
* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal * **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal
versions of requirements, generally used with `--prefer-stable`. versions of requirements, generally used with `--prefer-stable`.
@ -258,7 +258,7 @@ If you do not specify a package, Composer will prompt you to search for a packag
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement(`php`, * **--ignore-platform-req:** ignore a specific platform requirement(`php`,
`hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
does not fulfill it. does not fulfill it. Multiple requirements can be ignored via wildcard.
* **--prefer-stable:** Prefer stable versions of dependencies. * **--prefer-stable:** Prefer stable versions of dependencies.
* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal * **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal
versions of requirements, generally used with `--prefer-stable`. versions of requirements, generally used with `--prefer-stable`.
@ -303,7 +303,7 @@ uninstalled.
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement(`php`, * **--ignore-platform-req:** ignore a specific platform requirement(`php`,
`hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
does not fulfill it. does not fulfill it. Multiple requirements can be ignored via wildcard.
* **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to * **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to
get a faster autoloader. This is recommended especially for production, but get a faster autoloader. This is recommended especially for production, but
can take a bit of time to run so it is currently not done by default. can take a bit of time to run so it is currently not done by default.
@ -358,7 +358,7 @@ php composer.phar reinstall "acme/*"
reinstall command. reinstall command.
* **--ignore-platform-req:** ignore a specific platform requirement. This only * **--ignore-platform-req:** ignore a specific platform requirement. This only
has an effect in the context of the autoloader generation for the has an effect in the context of the autoloader generation for the
reinstall command. reinstall command. Multiple requirements can be ignored via wildcard.
## check-platform-reqs ## check-platform-reqs
@ -839,7 +839,7 @@ By default the command checks for the packages on packagist.org.
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement(`php`, * **--ignore-platform-req:** ignore a specific platform requirement(`php`,
`hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine `hhvm`, `lib-*` and `ext-*`) and force the installation even if the local machine
does not fulfill it. does not fulfill it. Multiple requirements can be ignored via wildcard.
* **--ask:** Ask user to provide target directory for new project. * **--ask:** Ask user to provide target directory for new project.
## dump-autoload (dumpautoload) ## dump-autoload (dumpautoload)
@ -874,6 +874,7 @@ performance.
See also the [`platform`](06-config.md#platform) config option. See also the [`platform`](06-config.md#platform) config option.
* **--ignore-platform-req:** ignore a specific platform requirement (`php`, `hhvm`, * **--ignore-platform-req:** ignore a specific platform requirement (`php`, `hhvm`,
`lib-*` and `ext-*`) and skip the [platform check](07-runtime.md#platform-check) for it. `lib-*` and `ext-*`) and skip the [platform check](07-runtime.md#platform-check) for it.
Multiple requirements can be ignored via wildcard.
## clear-cache / clearcache / cc ## clear-cache / clearcache / cc

View File

@ -2,21 +2,22 @@
namespace Composer\Filter\PlatformRequirementFilter; namespace Composer\Filter\PlatformRequirementFilter;
use Composer\Package\BasePackage;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFilterInterface final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFilterInterface
{ {
/** /**
* @var string[] * @var string
*/ */
private $reqList; private $regexp;
/** /**
* @param string[] $reqList * @param string[] $reqList
*/ */
public function __construct(array $reqList) public function __construct(array $reqList)
{ {
$this->reqList = $reqList; $this->regexp = BasePackage::packageNamesToRegexp($reqList);
} }
/** /**
@ -29,6 +30,6 @@ final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFi
return false; return false;
} }
return in_array($req, $this->reqList, true); return 1 === preg_match($this->regexp, $req);
} }
} }

View File

@ -263,4 +263,23 @@ abstract class BasePackage implements PackageInterface
return sprintf($wrap, $cleanedAllowPattern); return sprintf($wrap, $cleanedAllowPattern);
} }
/**
* Build a regexp from package names, expanding * globs as required
*
* @param string[] $packageNames
* @param string $wrap
* @return string
*/
public static function packageNamesToRegexp(array $packageNames, $wrap = '{^(?:%s)$}iD')
{
$packageNames = array_map(
function ($packageName) {
return BasePackage::packageNameToRegexp($packageName, '%s');
},
$packageNames
);
return sprintf($wrap, implode('|', $packageNames));
}
} }

View File

@ -40,17 +40,13 @@ class FilterRepository implements RepositoryInterface
if (!is_array($options['only'])) { if (!is_array($options['only'])) {
throw new \InvalidArgumentException('"only" key for repository '.$repo->getRepoName().' should be an array'); throw new \InvalidArgumentException('"only" key for repository '.$repo->getRepoName().' should be an array');
} }
$this->only = '{^(?:'.implode('|', array_map(function ($val) { $this->only = BasePackage::packageNamesToRegexp($options['only']);
return BasePackage::packageNameToRegexp($val, '%s');
}, $options['only'])) .')$}iD';
} }
if (isset($options['exclude'])) { if (isset($options['exclude'])) {
if (!is_array($options['exclude'])) { if (!is_array($options['exclude'])) {
throw new \InvalidArgumentException('"exclude" key for repository '.$repo->getRepoName().' should be an array'); throw new \InvalidArgumentException('"exclude" key for repository '.$repo->getRepoName().' should be an array');
} }
$this->exclude = '{^(?:'.implode('|', array_map(function ($val) { $this->exclude = BasePackage::packageNamesToRegexp($options['exclude']);
return BasePackage::packageNameToRegexp($val, '%s');
}, $options['exclude'])) .')$}iD';
} }
if ($this->exclude && $this->only) { if ($this->exclude && $this->only) {
throw new \InvalidArgumentException('Only one of "only" and "exclude" can be specified for repository '.$repo->getRepoName()); throw new \InvalidArgumentException('Only one of "only" and "exclude" can be specified for repository '.$repo->getRepoName());

View File

@ -1808,6 +1808,20 @@ EOF;
array(), array(),
array('php', 'ext-pdo'), array('php', 'ext-pdo'),
), ),
'Via wildcard ignored platform requirements are not checked for' => array(
array(
new Link('a', 'php', $versionParser->parseConstraints('^7.2.8')),
new Link('a', 'ext-xml', $versionParser->parseConstraints('*')),
new Link('a', 'ext-json', $versionParser->parseConstraints('*')),
new Link('a', 'ext-fileinfo', $versionParser->parseConstraints('*')),
new Link('a', 'ext-filesystem', $versionParser->parseConstraints('*')),
new Link('a', 'ext-filter', $versionParser->parseConstraints('*')),
),
'no_php_required',
array(),
array(),
array('php', 'ext-fil*'),
),
'No extensions required' => array( 'No extensions required' => array(
array( array(
new Link('a', 'php', $versionParser->parseConstraints('^7.2')), new Link('a', 'php', $versionParser->parseConstraints('^7.2')),

View File

@ -30,6 +30,14 @@ final class IgnoreListPlatformRequirementFilterTest extends TestCase
'ext-json is ignored if listed' => array(array('ext-json', 'monolog/monolog'), 'ext-json', true), 'ext-json is ignored if listed' => array(array('ext-json', 'monolog/monolog'), 'ext-json', true),
'php is not ignored if not listed' => array(array('ext-json', 'monolog/monolog'), 'php', false), 'php is not ignored if not listed' => array(array('ext-json', 'monolog/monolog'), 'php', false),
'monolog/monolog is not ignored even if listed' => array(array('ext-json', 'monolog/monolog'), 'monolog/monolog', false), 'monolog/monolog is not ignored even if listed' => array(array('ext-json', 'monolog/monolog'), 'monolog/monolog', false),
'ext-json is ignored if ext-* is listed' => array(array('ext-*'), 'ext-json', true),
'php is ignored if php* is listed' => array(array('ext-*', 'php*'), 'php', true),
'ext-json is ignored if * is listed' => array(array('foo', '*'), 'ext-json', true),
'php is ignored if * is listed' => array(array('*', 'foo'), 'php', true),
'monolog/monolog is not ignored even if * or monolog/* are listed' => array(array('*', 'monolog/*'), 'monolog/monolog', false),
'empty list entry does not ignore' => array(array(''), 'ext-foo', false),
'empty array does not ignore' => array(array(), 'ext-foo', false),
'list entries are not completing each other' => array(array('ext-', 'foo'), 'ext-foo', false),
); );
} }
} }

View File

@ -0,0 +1,22 @@
--TEST--
Install with ignore-platform-req list
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{ "name": "a/a", "version": "1.0.0", "require": { "ext-foo-bar": "*", "php": "98" } }
]
}
],
"require": {
"a/a": "1.0.0",
"php": "99.9",
"ext-foo-baz": "*"
}
}
--RUN--
install --ignore-platform-req=php --ignore-platform-req=ext-foo-bar --ignore-platform-req=ext-foo-baz
--EXPECT--
Installing a/a (1.0.0)

View File

@ -0,0 +1,22 @@
--TEST--
Install with ignore-platform-req wildcard
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{ "name": "a/a", "version": "1.0.0", "require": { "ext-foo-bar": "*", "php": "98" } }
]
}
],
"require": {
"a/a": "1.0.0",
"php": "99.9",
"ext-foo-baz": "*"
}
}
--RUN--
install --ignore-platform-req=php --ignore-platform-req=ext-foo-*
--EXPECT--
Installing a/a (1.0.0)

View File

@ -0,0 +1,26 @@
--TEST--
Update with ignore-platform-req list
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{ "name": "a/a", "version": "1.0.1", "require": { "ext-foo-bar": "*" } }
]
}
],
"require": {
"a/a": "1.0.*",
"php": "99.9",
"ext-foo-baz": "9"
}
}
--INSTALLED--
[
{ "name": "a/a", "version": "1.0.0" }
]
--RUN--
update --ignore-platform-req=php --ignore-platform-req=ext-foo-bar --ignore-platform-req=ext-foo-baz
--EXPECT--
Upgrading a/a (1.0.0 => 1.0.1)

View File

@ -0,0 +1,26 @@
--TEST--
Update with ignore-platform-req wildcard
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{ "name": "a/a", "version": "1.0.1", "require": { "ext-foo-bar": "*" } }
]
}
],
"require": {
"a/a": "1.0.*",
"php": "99.9",
"ext-foo-baz": "9"
}
}
--INSTALLED--
[
{ "name": "a/a", "version": "1.0.0" }
]
--RUN--
update --ignore-platform-req=php --ignore-platform-req=ext-foo-*
--EXPECT--
Upgrading a/a (1.0.0 => 1.0.1)

View File

@ -92,4 +92,33 @@ class BasePackageTest extends TestCase
return array_map($createPackage, $data); return array_map($createPackage, $data);
} }
/**
* @param string[] $packageNames
* @param string $wrap
* @param string $expectedRegexp
*
* @dataProvider dataPackageNamesToRegexp
*/
public function testPackageNamesToRegexp(array $packageNames, $wrap, $expectedRegexp)
{
$regexp = BasePackage::packageNamesToRegexp($packageNames, $wrap);
$this->assertSame($expectedRegexp, $regexp);
}
/**
* @return mixed[][]
*/
public function dataPackageNamesToRegexp()
{
return array(
array(
array('ext-*', 'monolog/monolog'), '{^%s$}i', '{^ext\-.*|monolog/monolog$}i',
array('php'), '{^%s$}i', '{^php$}i',
array('*'), '{^%s$}i', '{^.*$}i',
array('foo', 'bar'), '§%s§', '§foo|bar§',
)
);
}
} }