1
0
Fork 0

Add tests for platform packages required by root and avoid creating rules altogether instead of disabling them, refs #3320

pull/3148/merge
Jordi Boggiano 2014-10-17 15:26:00 +01:00
parent 71976a638c
commit ec0463a400
10 changed files with 68 additions and 48 deletions

View File

@ -45,7 +45,7 @@ class InstallCommand extends Command
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
new InputOption('ignore-platform-package-requirements', null, InputOption::VALUE_NONE, 'Ignore PHP Extention requirements.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
)) ))
->setHelp(<<<EOT ->setHelp(<<<EOT
@ -115,7 +115,7 @@ EOT
->setDevMode(!$input->getOption('no-dev')) ->setDevMode(!$input->getOption('no-dev'))
->setRunScripts(!$input->getOption('no-scripts')) ->setRunScripts(!$input->getOption('no-scripts'))
->setOptimizeAutoloader($optimize) ->setOptimizeAutoloader($optimize)
->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements')); ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
; ;
if ($input->getOption('no-plugins')) { if ($input->getOption('no-plugins')) {

View File

@ -46,7 +46,7 @@ class UpdateCommand extends Command
new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'), new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
new InputOption('ignore-platform-package-requirements', null, InputOption::VALUE_NONE, 'Ignore PHP Extention requirements.'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
)) ))
->setHelp(<<<EOT ->setHelp(<<<EOT
The <info>update</info> command reads the composer.json file from the The <info>update</info> command reads the composer.json file from the
@ -120,7 +120,7 @@ EOT
->setUpdate(true) ->setUpdate(true)
->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages')) ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
->setWhitelistDependencies($input->getOption('with-dependencies')) ->setWhitelistDependencies($input->getOption('with-dependencies'))
->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements')); ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
; ;
if ($input->getOption('no-plugins')) { if ($input->getOption('no-plugins')) {

View File

@ -43,7 +43,17 @@ class Request
$this->addJob($packageName, 'remove', $constraint); $this->addJob($packageName, 'remove', $constraint);
} }
protected function addJob($packageName, $cmd, LinkConstraintInterface $constraint = null) /**
* Mark an existing package as being installed and having to remain installed
*
* These jobs will not be tempered with by the solver
*/
public function fix($packageName, LinkConstraintInterface $constraint = null)
{
$this->addJob($packageName, 'install', $constraint, true);
}
protected function addJob($packageName, $cmd, LinkConstraintInterface $constraint = null, $fixed = false)
{ {
$packageName = strtolower($packageName); $packageName = strtolower($packageName);
@ -51,6 +61,7 @@ class Request
'cmd' => $cmd, 'cmd' => $cmd,
'packageName' => $packageName, 'packageName' => $packageName,
'constraint' => $constraint, 'constraint' => $constraint,
'fixed' => $fixed
); );
} }

View File

@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Package\AliasPackage; use Composer\Package\AliasPackage;
use Composer\Repository\PlatformRepository;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
@ -178,7 +179,7 @@ class RuleSetGenerator
} }
} }
protected function addRulesForPackage(PackageInterface $package) protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
{ {
$workQueue = new \SplQueue; $workQueue = new \SplQueue;
$workQueue->enqueue($package); $workQueue->enqueue($package);
@ -192,6 +193,10 @@ class RuleSetGenerator
$this->addedMap[$package->getId()] = true; $this->addedMap[$package->getId()] = true;
foreach ($package->getRequires() as $link) { foreach ($package->getRequires() as $link) {
if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
continue;
}
$possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint()); $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
$this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link)); $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
@ -264,12 +269,12 @@ class RuleSetGenerator
* @param PackageInterface $package Rules for this package's updates are to * @param PackageInterface $package Rules for this package's updates are to
* be added * be added
*/ */
private function addRulesForUpdatePackages(PackageInterface $package) private function addRulesForUpdatePackages(PackageInterface $package, $ignorePlatformReqs)
{ {
$updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package); $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
foreach ($updates as $update) { foreach ($updates as $update) {
$this->addRulesForPackage($update); $this->addRulesForPackage($update, $ignorePlatformReqs);
} }
} }
@ -296,16 +301,20 @@ class RuleSetGenerator
} }
} }
protected function addRulesForJobs() protected function addRulesForJobs($ignorePlatformReqs)
{ {
foreach ($this->jobs as $job) { foreach ($this->jobs as $job) {
switch ($job['cmd']) { switch ($job['cmd']) {
case 'install': case 'install':
if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
continue;
}
$packages = $this->pool->whatProvides($job['packageName'], $job['constraint']); $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
if ($packages) { if ($packages) {
foreach ($packages as $package) { foreach ($packages as $package) {
if (!isset($this->installedMap[$package->getId()])) { if (!isset($this->installedMap[$package->getId()])) {
$this->addRulesForPackage($package); $this->addRulesForPackage($package, $ignorePlatformReqs);
} }
} }
@ -326,7 +335,7 @@ class RuleSetGenerator
} }
} }
public function getRulesFor($jobs, $installedMap) public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
{ {
$this->jobs = $jobs; $this->jobs = $jobs;
$this->rules = new RuleSet; $this->rules = new RuleSet;
@ -343,11 +352,11 @@ class RuleSetGenerator
$this->addedMap = array(); $this->addedMap = array();
foreach ($this->installedMap as $package) { foreach ($this->installedMap as $package) {
$this->addRulesForPackage($package); $this->addRulesForPackage($package, $ignorePlatformReqs);
$this->addRulesForUpdatePackages($package); $this->addRulesForUpdatePackages($package, $ignorePlatformReqs);
} }
$this->addRulesForJobs(); $this->addRulesForJobs($ignorePlatformReqs);
return $this->rules; return $this->rules;
} }

View File

@ -130,7 +130,7 @@ class Solver
} }
} }
protected function checkForRootRequireProblems($ignorePlatformPackageRequirements) protected function checkForRootRequireProblems($ignorePlatformReqs)
{ {
foreach ($this->jobs as $job) { foreach ($this->jobs as $job) {
switch ($job['cmd']) { switch ($job['cmd']) {
@ -150,7 +150,7 @@ class Solver
break; break;
case 'install': case 'install':
if ($ignorePlatformPackageRequirements && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) { if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
break; break;
} }
@ -164,24 +164,16 @@ class Solver
} }
} }
public function solve(Request $request, $ignorePlatformPackage = false) public function solve(Request $request, $ignorePlatformReqs = false)
{ {
$this->jobs = $request->getJobs(); $this->jobs = $request->getJobs();
$this->setupInstalledMap(); $this->setupInstalledMap();
$this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap); $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
$this->checkForRootRequireProblems($ignorePlatformPackage); $this->checkForRootRequireProblems($ignorePlatformReqs);
$this->decisions = new Decisions($this->pool); $this->decisions = new Decisions($this->pool);
$this->watchGraph = new RuleWatchGraph; $this->watchGraph = new RuleWatchGraph;
if ($ignorePlatformPackage) {
foreach ($this->rules as $rule) {
if ($rule->getReason() === Rule::RULE_PACKAGE_REQUIRES && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $rule->getRequiredPackage())) {
$rule->disable();
}
}
}
foreach ($this->rules as $rule) { foreach ($this->rules as $rule) {
$this->watchGraph->insert(new RuleWatchNode($rule)); $this->watchGraph->insert(new RuleWatchNode($rule));
} }

View File

@ -105,7 +105,7 @@ class Installer
protected $verbose = false; protected $verbose = false;
protected $update = false; protected $update = false;
protected $runScripts = true; protected $runScripts = true;
protected $ignorePlatformPackage = false; protected $ignorePlatformReqs = false;
/** /**
* Array of package names/globs flagged for update * Array of package names/globs flagged for update
* *
@ -264,7 +264,7 @@ class Installer
$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request);
$solver = new Solver($policy, $pool, $installedRepo); $solver = new Solver($policy, $pool, $installedRepo);
$ops = $solver->solve($request, $this->ignorePlatformPackage); $ops = $solver->solve($request, $this->ignorePlatformReqs);
$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request, $ops); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request, $ops);
foreach ($ops as $op) { foreach ($ops as $op) {
if ($op->getJobType() === 'uninstall') { if ($op->getJobType() === 'uninstall') {
@ -471,7 +471,7 @@ class Installer
$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request);
$solver = new Solver($policy, $pool, $installedRepo); $solver = new Solver($policy, $pool, $installedRepo);
try { try {
$operations = $solver->solve($request, $this->ignorePlatformPackage); $operations = $solver->solve($request, $this->ignorePlatformReqs);
$this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request, $operations); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request, $operations);
} catch (SolverProblemsException $e) { } catch (SolverProblemsException $e) {
$this->io->write('<error>Your requirements could not be resolved to an installable set of packages.</error>'); $this->io->write('<error>Your requirements could not be resolved to an installable set of packages.</error>');
@ -658,6 +658,10 @@ class Installer
} }
$rootConstraints = array(); $rootConstraints = array();
foreach ($requires as $req => $constraint) { foreach ($requires as $req => $constraint) {
// skip platform requirements from the root package to avoid filtering out existing platform packages
if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
continue;
}
$rootConstraints[$req] = $constraint->getConstraint(); $rootConstraints[$req] = $constraint->getConstraint();
} }
@ -705,7 +709,7 @@ class Installer
|| !isset($provided[$package->getName()]) || !isset($provided[$package->getName()])
|| !$provided[$package->getName()]->getConstraint()->matches($constraint) || !$provided[$package->getName()]->getConstraint()->matches($constraint)
) { ) {
$request->install($package->getName(), $constraint); $request->fix($package->getName(), $constraint);
} }
} }
@ -1180,12 +1184,12 @@ class Installer
/** /**
* set ignore Platform Package requirements * set ignore Platform Package requirements
* *
* @param boolean $ignorePlatformPackage * @param boolean $ignorePlatformReqs
* @return Installer * @return Installer
*/ */
public function setIgnorePlatformPackage($ignorePlatformPackage = false) public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
{ {
$this->ignorePlatformPackage = (boolean) $ignorePlatformPackage; $this->ignorePlatformReqs = (boolean) $ignorePlatformReqs;
return $this; return $this;
} }

View File

@ -34,14 +34,14 @@ class RequestTest extends TestCase
$request = new Request($pool); $request = new Request($pool);
$request->install('foo'); $request->install('foo');
$request->install('bar'); $request->fix('bar');
$request->remove('foobar'); $request->remove('foobar');
$this->assertEquals( $this->assertEquals(
array( array(
array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => null), array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => null, 'fixed' => false),
array('cmd' => 'install', 'packageName' => 'bar', 'constraint' => null), array('cmd' => 'install', 'packageName' => 'bar', 'constraint' => null, 'fixed' => true),
array('cmd' => 'remove', 'packageName' => 'foobar', 'constraint' => null), array('cmd' => 'remove', 'packageName' => 'foobar', 'constraint' => null, 'fixed' => false),
), ),
$request->getJobs()); $request->getJobs());
} }
@ -66,7 +66,7 @@ class RequestTest extends TestCase
$this->assertEquals( $this->assertEquals(
array( array(
array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => $constraint), array('cmd' => 'install', 'packageName' => 'foo', 'constraint' => $constraint, 'fixed' => false),
), ),
$request->getJobs() $request->getJobs()
); );

View File

@ -1,20 +1,22 @@
--TEST-- --TEST--
Install in ignore-platform-package-requirements mode Install in ignore-platform-reqs mode
--COMPOSER-- --COMPOSER--
{ {
"repositories": [ "repositories": [
{ {
"type": "package", "type": "package",
"package": [ "package": [
{ "name": "a/a", "version": "1.0.0", "require": { "ext-testdummy": "*" } } { "name": "a/a", "version": "1.0.0", "require": { "ext-testdummy": "*", "php": "98" } }
] ]
} }
], ],
"require": { "require": {
"a/a": "1.0.0" "a/a": "1.0.0",
"php": "99.9",
"ext-dummy2": "3"
} }
} }
--RUN-- --RUN--
install --ignore-platform-package-requirements install --ignore-platform-reqs
--EXPECT-- --EXPECT--
Installing a/a (1.0.0) Installing a/a (1.0.0)

View File

@ -1,5 +1,5 @@
--TEST-- --TEST--
Update in ignore-platform-package-requirements mode Update in ignore-platform-reqs mode
--COMPOSER-- --COMPOSER--
{ {
"repositories": [ "repositories": [
@ -11,7 +11,9 @@ Update in ignore-platform-package-requirements mode
} }
], ],
"require": { "require": {
"a/a": "1.0.*" "a/a": "1.0.*",
"php": "99.9",
"ext-dummy2": "9"
} }
} }
--INSTALLED-- --INSTALLED--
@ -19,6 +21,6 @@ Update in ignore-platform-package-requirements mode
{ "name": "a/a", "version": "1.0.0" } { "name": "a/a", "version": "1.0.0" }
] ]
--RUN-- --RUN--
update --ignore-platform-package-requirements update --ignore-platform-reqs
--EXPECT-- --EXPECT--
Updating a/a (1.0.0) to a/a (1.0.1) Updating a/a (1.0.0) to a/a (1.0.1)

View File

@ -205,7 +205,7 @@ class InstallerTest extends TestCase
$installer $installer
->setDevMode(!$input->getOption('no-dev')) ->setDevMode(!$input->getOption('no-dev'))
->setDryRun($input->getOption('dry-run')) ->setDryRun($input->getOption('dry-run'))
->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements')); ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
return $installer->run(); return $installer->run();
}); });
@ -217,7 +217,7 @@ class InstallerTest extends TestCase
->setDryRun($input->getOption('dry-run')) ->setDryRun($input->getOption('dry-run'))
->setUpdateWhitelist($input->getArgument('packages')) ->setUpdateWhitelist($input->getArgument('packages'))
->setWhitelistDependencies($input->getOption('with-dependencies')) ->setWhitelistDependencies($input->getOption('with-dependencies'))
->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements')); ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
return $installer->run(); return $installer->run();
}); });