Browse Source

Code optimizations: avoid loops in match()

Jordi Boggiano 12 years ago
parent
commit
beb9a5bd72

+ 4 - 12
src/Composer/DependencyResolver/Pool.php

@@ -241,10 +241,6 @@ class Pool
             }
         }
 
-        if (!isset($this->packageByName[$name]) && !$candidates) {
-            return array();
-        }
-
         if (isset($this->packageByName[$name])) {
             $candidates = array_merge($candidates, $this->packageByName[$name]);
         }
@@ -390,16 +386,12 @@ class Pool
             $replaces = $candidate->getReplaces();
         }
 
-        foreach ($provides as $link) {
-            if ($link->getTarget() === $name && $constraint->matches($link->getConstraint())) {
-                return self::MATCH_PROVIDE;
-            }
+        if (isset($provides[$name]) && $constraint->matches($provides[$name]->getConstraint())) {
+            return self::MATCH_PROVIDE;
         }
 
-        foreach ($replaces as $link) {
-            if ($link->getTarget() === $name && $constraint->matches($link->getConstraint())) {
-                return self::MATCH_REPLACE;
-            }
+        if (isset($replaces[$name]) && $constraint->matches($replaces[$name]->getConstraint())) {
+            return self::MATCH_REPLACE;
         }
 
         return self::MATCH_NONE;

+ 1 - 1
src/Composer/Package/Version/VersionParser.php

@@ -186,7 +186,7 @@ class VersionParser
             } else {
                 $parsedConstraint = $this->parseConstraints($constraint);
             }
-            $res[] = new Link($source, $target, $parsedConstraint, $description, $constraint);
+            $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
         }
 
         return $res;

+ 66 - 59
tests/Composer/Test/DependencyResolver/SolverTest.php

@@ -19,6 +19,7 @@ use Composer\DependencyResolver\Solver;
 use Composer\DependencyResolver\SolverProblemsException;
 use Composer\Package\Link;
 use Composer\Test\TestCase;
+use Composer\Package\LinkConstraint\MultiConstraint;
 
 class SolverTest extends TestCase
 {
@@ -103,7 +104,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
 
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
 
         $this->reposComplete();
 
@@ -124,9 +125,11 @@ class SolverTest extends TestCase
         $this->repo->addPackage($newPackageB13 = $this->getPackage('B', '1.3'));
 
         $packageA->setRequires(array(
-            new Link('A', 'B', $this->getVersionConstraint('<=', '1.3'), 'requires'),
-            new Link('A', 'B', $this->getVersionConstraint('<>', '1.3'), 'requires'),
-            new Link('A', 'B', $this->getVersionConstraint('!=', '1.2'), 'requires'),
+            'b' => new Link('A', 'B', new MultiConstraint(array(
+                $this->getVersionConstraint('<=', '1.3'),
+                $this->getVersionConstraint('<>', '1.3'),
+                $this->getVersionConstraint('!=', '1.2'),
+            )), 'requires'),
         ));
 
         $this->reposComplete();
@@ -146,11 +149,11 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageC = $this->getPackage('C', '1.0'));
 
         $packageB->setRequires(array(
-            new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
-            new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
         $packageC->setRequires(array(
-            new Link('C', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
 
         $this->reposComplete();
@@ -216,7 +219,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
         $this->reposComplete();
 
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0.0.0'), 'requires')));
 
         $this->request->install('A', $this->getVersionConstraint('=', '1.0.0.0'));
         $this->request->install('B', $this->getVersionConstraint('=', '1.1.0.0'));
@@ -249,8 +252,8 @@ class SolverTest extends TestCase
         $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1'));
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
 
-        $packageA->setRequires(array(new Link('A', 'B', null, 'requires')));
-        $newPackageA->setRequires(array(new Link('A', 'B', null, 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', null, 'requires')));
+        $newPackageA->setRequires(array('b' => new Link('A', 'B', null, 'requires')));
 
         $this->reposComplete();
 
@@ -361,7 +364,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
         $this->repo->addPackage($packageC = $this->getPackage('C', '1.1'));
         $this->repo->addPackage($this->getPackage('D', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
 
         $this->reposComplete();
 
@@ -384,8 +387,8 @@ class SolverTest extends TestCase
         $this->repo->addPackage($middlePackageB = $this->getPackage('B', '1.0'));
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
         $this->repo->addPackage($oldPackageB = $this->getPackage('B', '0.9'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
-        $packageA->setConflicts(array(new Link('A', 'B', $this->getVersionConstraint('<', '1.0'), 'conflicts')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.1'), 'requires')));
+        $packageA->setConflicts(array('b' => new Link('A', 'B', $this->getVersionConstraint('<', '1.0'), 'conflicts')));
 
         $this->reposComplete();
 
@@ -401,7 +404,7 @@ class SolverTest extends TestCase
     {
         $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
-        $packageB->setReplaces(array(new Link('B', 'A', null)));
+        $packageB->setReplaces(array('a' => new Link('B', 'A', null)));
 
         $this->reposComplete();
 
@@ -430,8 +433,8 @@ class SolverTest extends TestCase
     {
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageQ->setProvides(array(new Link('Q', 'B', $this->getVersionConstraint('=', '1.0'), 'provides')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageQ->setProvides(array('b' => new Link('Q', 'B', $this->getVersionConstraint('=', '1.0'), 'provides')));
 
         $this->reposComplete();
 
@@ -448,8 +451,8 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
 
         $this->reposComplete();
 
@@ -465,8 +468,8 @@ class SolverTest extends TestCase
     {
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
 
         $this->reposComplete();
 
@@ -483,8 +486,8 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageQ = $this->getPackage('Q', '1.0'));
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageQ->setReplaces(array(new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageQ->setReplaces(array('b' => new Link('Q', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces')));
 
         $this->reposComplete();
 
@@ -501,24 +504,28 @@ class SolverTest extends TestCase
     {
         $this->repo->addPackage($packageX = $this->getPackage('X', '1.0'));
         $packageX->setRequires(array(
-            new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'),
-            new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires')));
+            'a' => new Link('X', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires'),
+            'b' => new Link('X', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires')
+        ));
 
         $this->repo->addPackage($packageA = $this->getPackage('A', '2.0.0'));
         $this->repo->addPackage($newPackageA = $this->getPackage('A', '2.1.0'));
         $this->repo->addPackage($newPackageB = $this->getPackage('B', '2.1.0'));
 
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'requires')));
 
         // new package A depends on version of package B that does not exist
         // => new package A is not installable
-        $newPackageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '2.2.0.0'), 'requires')));
+        $newPackageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.2.0.0'), 'requires')));
 
         // add a package S replacing both A and B, so that S and B or S and A cannot be simultaneously installed
         // but an alternative option for A and B both exists
         // this creates a more difficult so solve conflict
         $this->repo->addPackage($packageS = $this->getPackage('S', '2.0.0'));
-        $packageS->setReplaces(array(new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'), new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces')));
+        $packageS->setReplaces(array(
+            'a' => new Link('S', 'A', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces'),
+            'b' => new Link('S', 'B', $this->getVersionConstraint('>=', '2.0.0.0'), 'replaces')
+        ));
 
         $this->reposComplete();
 
@@ -536,8 +543,8 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
         $this->repo->addPackage($packageB1 = $this->getPackage('B', '0.9'));
         $this->repo->addPackage($packageB2 = $this->getPackage('B', '1.1'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageB2->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('>=', '1.0'), 'requires')));
 
         $this->reposComplete();
 
@@ -555,13 +562,13 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
         $this->repo->addPackage($packageC = $this->getPackage('C', '1.0'));
         $this->repo->addPackage($packageD = $this->getPackage('D', '1.0'));
-        $packageA->setRequires(array(new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageB->setRequires(array(new Link('B', 'Virtual', $this->getVersionConstraint('>=', '1.0'), 'requires')));
-        $packageC->setProvides(array(new Link('C', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
-        $packageD->setProvides(array(new Link('D', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
+        $packageA->setRequires(array('b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageB->setRequires(array('virtual' => new Link('B', 'Virtual', $this->getVersionConstraint('>=', '1.0'), 'requires')));
+        $packageC->setProvides(array('virtual' => new Link('C', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
+        $packageD->setProvides(array('virtual' => new Link('D', 'Virtual', $this->getVersionConstraint('==', '1.0'), 'provides')));
 
-        $packageC->setRequires(array(new Link('C', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
-        $packageD->setRequires(array(new Link('D', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
+        $packageC->setRequires(array('a' => new Link('C', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
+        $packageD->setRequires(array('a' => new Link('D', 'A', $this->getVersionConstraint('==', '1.0'), 'requires')));
 
         $this->reposComplete();
 
@@ -586,18 +593,18 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageD2 = $this->getPackage('D', '1.1'));
 
         $packageA->setRequires(array(
-            new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
-            new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
 
         $packageD->setReplaces(array(
-            new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
-            new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
+            'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
+            'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
         ));
 
         $packageD2->setReplaces(array(
-            new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
-            new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
+            'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
+            'c' => new Link('D', 'C', $this->getVersionConstraint('>=', '1.0'), 'replaces'),
         ));
 
         $this->reposComplete();
@@ -621,19 +628,19 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageD = $this->getPackage('D', '2.0.9'));
 
         $packageC->setRequires(array(
-            new Link('C', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
-            new Link('C', 'D', $this->getVersionConstraint('>=', '2.0'), 'requires'),
+            'a' => new Link('C', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
+            'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '2.0'), 'requires'),
         ));
 
         $packageD->setRequires(array(
-            new Link('D', 'A', $this->getVersionConstraint('>=', '2.1'), 'requires'),
-            new Link('D', 'B', $this->getVersionConstraint('>=', '2.0-dev'), 'requires'),
+            'a' => new Link('D', 'A', $this->getVersionConstraint('>=', '2.1'), 'requires'),
+            'b' => new Link('D', 'B', $this->getVersionConstraint('>=', '2.0-dev'), 'requires'),
         ));
 
-        $packageB1->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
-        $packageB2->setRequires(array(new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
+        $packageB1->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
+        $packageB2->setRequires(array('a' => new Link('B', 'A', $this->getVersionConstraint('==', '2.1.0.0-dev'), 'requires')));
 
-        $packageB2->setReplaces(array(new Link('B', 'D', $this->getVersionConstraint('==', '2.0.9.0'), 'replaces')));
+        $packageB2->setReplaces(array('d' => new Link('B', 'D', $this->getVersionConstraint('==', '2.0.9.0'), 'replaces')));
 
         $this->reposComplete();
 
@@ -650,7 +657,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));;
 
         $packageA->setConflicts(array(
-            new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'conflicts'),
+            'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'conflicts'),
         ));
 
         $this->reposComplete();
@@ -680,7 +687,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
 
         $packageA->setRequires(array(
-            new Link('A', 'B', $this->getVersionConstraint('>=', '2.0'), 'requires'),
+            'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '2.0'), 'requires'),
         ));
 
         $this->reposComplete();
@@ -717,16 +724,16 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageD = $this->getPackage('D', '1.0'));
 
         $packageA->setRequires(array(
-            new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'b' => new Link('A', 'B', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
         $packageB->setRequires(array(
-            new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'c' => new Link('B', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
         $packageC->setRequires(array(
-            new Link('C', 'D', $this->getVersionConstraint('>=', '1.0'), 'requires'),
+            'd' => new Link('C', 'D', $this->getVersionConstraint('>=', '1.0'), 'requires'),
         ));
         $packageD->setRequires(array(
-            new Link('D', 'B', $this->getVersionConstraint('<', '1.0'), 'requires'),
+            'b' => new Link('D', 'B', $this->getVersionConstraint('<', '1.0'), 'requires'),
         ));
 
         $this->reposComplete();
@@ -761,11 +768,11 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageTwigBridge = $this->getPackage('symfony/twig-bridge', '2.0'));
 
         $packageTwigBridge->setRequires(array(
-            new Link('symfony/twig-bridge', 'twig/twig', $this->getVersionConstraint('<', '2.0'), 'requires'),
+            'twig/twig' => new Link('symfony/twig-bridge', 'twig/twig', $this->getVersionConstraint('<', '2.0'), 'requires'),
         ));
 
         $packageSymfony->setReplaces(array(
-            new Link('symfony/symfony', 'symfony/twig-bridge', $this->getVersionConstraint('==', '2.0'), 'replaces'),
+            'symfony/twig-bridge' => new Link('symfony/symfony', 'symfony/twig-bridge', $this->getVersionConstraint('==', '2.0'), 'replaces'),
         ));
 
         $this->reposComplete();
@@ -786,10 +793,10 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageA2 = $this->getPackage('A', '2.0'));
 
         $packageA2->setRequires(array(
-            new Link('A', 'B', $this->getVersionConstraint('==', '2.0'), 'requires', '== 2.0'),
+            'b' => new Link('A', 'B', $this->getVersionConstraint('==', '2.0'), 'requires', '== 2.0'),
         ));
         $packageB->setRequires(array(
-            new Link('B', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
+            'a' => new Link('B', 'A', $this->getVersionConstraint('>=', '2.0'), 'requires'),
         ));
 
         $this->repo->addPackage($packageA2Alias = $this->getAliasPackage($packageA2, '1.1'));
@@ -811,7 +818,7 @@ class SolverTest extends TestCase
         $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
 
         $packageB->setRequires(array(
-            new Link('B', 'A', $this->getVersionConstraint('<', '2.0'), 'requires'),
+            'a' => new Link('B', 'A', $this->getVersionConstraint('<', '2.0'), 'requires'),
         ));
 
         $this->repo->addPackage($packageAAlias = $this->getAliasPackage($packageA, '1.1'));

+ 1 - 1
tests/Composer/Test/Package/Loader/ArrayLoaderTest.php

@@ -34,7 +34,7 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase
 
         $package = $this->loader->load($config);
         $replaces = $package->getReplaces();
-        $this->assertEquals('== 1.2.3.4', (string) $replaces[0]->getConstraint());
+        $this->assertEquals('== 1.2.3.4', (string) $replaces['foo']->getConstraint());
     }
 
     public function testTypeDefault()