Browse Source

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

Jordi Boggiano 10 years ago
parent
commit
ec0463a400

+ 2 - 2
src/Composer/Command/InstallCommand.php

@@ -45,7 +45,7 @@ class InstallCommand extends Command
                 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('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.'),
             ))
             ->setHelp(<<<EOT
@@ -115,7 +115,7 @@ EOT
             ->setDevMode(!$input->getOption('no-dev'))
             ->setRunScripts(!$input->getOption('no-scripts'))
             ->setOptimizeAutoloader($optimize)
-            ->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements'));
+            ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
         ;
 
         if ($input->getOption('no-plugins')) {

+ 2 - 2
src/Composer/Command/UpdateCommand.php

@@ -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('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('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
 The <info>update</info> command reads the composer.json file from the
@@ -120,7 +120,7 @@ EOT
             ->setUpdate(true)
             ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $input->getArgument('packages'))
             ->setWhitelistDependencies($input->getOption('with-dependencies'))
-            ->setIgnorePlatformPackage($input->getOption('ignore-platform-package-requirements'));
+            ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));
         ;
 
         if ($input->getOption('no-plugins')) {

+ 12 - 1
src/Composer/DependencyResolver/Request.php

@@ -43,7 +43,17 @@ class Request
         $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);
 
@@ -51,6 +61,7 @@ class Request
             'cmd' => $cmd,
             'packageName' => $packageName,
             'constraint' => $constraint,
+            'fixed' => $fixed
         );
     }
 

+ 18 - 9
src/Composer/DependencyResolver/RuleSetGenerator.php

@@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
 
 use Composer\Package\PackageInterface;
 use Composer\Package\AliasPackage;
+use Composer\Repository\PlatformRepository;
 
 /**
  * @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->enqueue($package);
@@ -192,6 +193,10 @@ class RuleSetGenerator
             $this->addedMap[$package->getId()] = true;
 
             foreach ($package->getRequires() as $link) {
+                if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
+                    continue;
+                }
+
                 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
 
                 $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
      *                                  be added
      */
-    private function addRulesForUpdatePackages(PackageInterface $package)
+    private function addRulesForUpdatePackages(PackageInterface $package, $ignorePlatformReqs)
     {
         $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
 
         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) {
             switch ($job['cmd']) {
                 case 'install':
+                    if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
+                        continue;
+                    }
+
                     $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
                     if ($packages) {
                         foreach ($packages as $package) {
                             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->rules = new RuleSet;
@@ -343,11 +352,11 @@ class RuleSetGenerator
 
         $this->addedMap = array();
         foreach ($this->installedMap as $package) {
-            $this->addRulesForPackage($package);
-            $this->addRulesForUpdatePackages($package);
+            $this->addRulesForPackage($package, $ignorePlatformReqs);
+            $this->addRulesForUpdatePackages($package, $ignorePlatformReqs);
         }
 
-        $this->addRulesForJobs();
+        $this->addRulesForJobs($ignorePlatformReqs);
 
         return $this->rules;
     }

+ 5 - 13
src/Composer/DependencyResolver/Solver.php

@@ -130,7 +130,7 @@ class Solver
         }
     }
 
-    protected function checkForRootRequireProblems($ignorePlatformPackageRequirements)
+    protected function checkForRootRequireProblems($ignorePlatformReqs)
     {
         foreach ($this->jobs as $job) {
             switch ($job['cmd']) {
@@ -150,7 +150,7 @@ class Solver
                     break;
 
                 case 'install':
-                    if ($ignorePlatformPackageRequirements && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
+                    if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
                         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->setupInstalledMap();
-        $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap);
-        $this->checkForRootRequireProblems($ignorePlatformPackage);
+        $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
+        $this->checkForRootRequireProblems($ignorePlatformReqs);
         $this->decisions = new Decisions($this->pool);
         $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) {
             $this->watchGraph->insert(new RuleWatchNode($rule));
         }

+ 11 - 7
src/Composer/Installer.php

@@ -105,7 +105,7 @@ class Installer
     protected $verbose = false;
     protected $update = false;
     protected $runScripts = true;
-    protected $ignorePlatformPackage = false;
+    protected $ignorePlatformReqs = false;
     /**
      * 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);
                     $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);
                     foreach ($ops as $op) {
                         if ($op->getJobType() === 'uninstall') {
@@ -471,7 +471,7 @@ class Installer
         $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $policy, $pool, $installedRepo, $request);
         $solver = new Solver($policy, $pool, $installedRepo);
         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);
         } catch (SolverProblemsException $e) {
             $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();
         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();
         }
 
@@ -705,7 +709,7 @@ class Installer
                 || !isset($provided[$package->getName()])
                 || !$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
      *
-     * @param  boolean   $ignorePlatformPackage
+     * @param  boolean   $ignorePlatformReqs
      * @return Installer
      */
-    public function setIgnorePlatformPackage($ignorePlatformPackage = false)
+    public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
     {
-        $this->ignorePlatformPackage = (boolean) $ignorePlatformPackage;
+        $this->ignorePlatformReqs = (boolean) $ignorePlatformReqs;
 
         return $this;
     }

+ 5 - 5
tests/Composer/Test/DependencyResolver/RequestTest.php

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

+ 6 - 4
tests/Composer/Test/Fixtures/installer/install-ignore-platform-package-requirements.test

@@ -1,20 +1,22 @@
 --TEST--
-Install in ignore-platform-package-requirements mode
+Install in ignore-platform-reqs mode
 --COMPOSER--
 {
     "repositories": [
         {
             "type": "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": {
-        "a/a": "1.0.0"
+        "a/a": "1.0.0",
+        "php": "99.9",
+        "ext-dummy2": "3"
     }
 }
 --RUN--
-install --ignore-platform-package-requirements
+install --ignore-platform-reqs
 --EXPECT--
 Installing a/a (1.0.0)

+ 5 - 3
tests/Composer/Test/Fixtures/installer/update-ignore-platform-package-requirements.test

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

+ 2 - 2
tests/Composer/Test/InstallerTest.php

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