Browse Source

Revert "Merge remote-tracking branch 'naderman/load-no-providers'"

This reverts commit 3e85f82373aa7a05c7cc85a7f6d4725690713197, reversing
changes made to b025d0982b78ad76d381d16f8303d6b0769fc5ea.
Nils Adermann 9 years ago
parent
commit
75c501251d

+ 0 - 1
src/Composer/Command/CreateProjectCommand.php

@@ -276,7 +276,6 @@ EOT
 
         $pool = new Pool($stability);
         $pool->addRepository($sourceRepo);
-        $pool->loadRecursively(array($name));
 
         // find the latest version if there are multiple
         $versionSelector = new VersionSelector($pool);

+ 47 - 73
src/Composer/DependencyResolver/Pool.php

@@ -99,9 +99,40 @@ class Pool
             if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
                 $this->providerRepos[] = $repo;
                 $repo->setRootAliases($rootAliases);
+                $repo->resetPackageIds();
             } else {
                 foreach ($repo->getPackages() as $package) {
-                    $this->loadPackage($package, $rootAliases, $exempt);
+                    $names = $package->getNames();
+                    $stability = $package->getStability();
+                    if ($exempt || $this->isPackageAcceptable($names, $stability)) {
+                        $package->setId($this->id++);
+                        $this->packages[] = $package;
+                        $this->packageByExactName[$package->getName()][$package->id] = $package;
+
+                        foreach ($names as $provided) {
+                            $this->packageByName[$provided][] = $package;
+                        }
+
+                        // handle root package aliases
+                        $name = $package->getName();
+                        if (isset($rootAliases[$name][$package->getVersion()])) {
+                            $alias = $rootAliases[$name][$package->getVersion()];
+                            if ($package instanceof AliasPackage) {
+                                $package = $package->getAliasOf();
+                            }
+                            $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
+                            $aliasPackage->setRootPackageAlias(true);
+                            $aliasPackage->setId($this->id++);
+
+                            $package->getRepository()->addPackage($aliasPackage);
+                            $this->packages[] = $aliasPackage;
+                            $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
+
+                            foreach ($aliasPackage->getNames() as $name) {
+                                $this->packageByName[$name][] = $aliasPackage;
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -129,38 +160,6 @@ class Pool
         return $this->packages[$id - 1];
     }
 
-    /**
-     * Ensures that all given names and their requirements are loaded.
-     *
-     * @param array $packageNames A list of names that need to be available
-     */
-    public function loadRecursively(array $packageNames)
-    {
-        $loadedMap = array();
-        do {
-            $newPackageNames = array();
-            $loadedCount = count($loadedMap);
-
-            foreach ($this->providerRepos as $repo) {
-                $packages = $repo->loadRecursively(
-                    $packageNames,
-                    array($this, 'isPackageAcceptable')
-                );
-
-                foreach ($packages as $package) {
-                    $name = $package->getName();
-                    if (!isset($loadedMap[$name])) {
-                        $loadedMap[$name] = true;
-                        $newPackageNames[] = $name;
-                    }
-                    $this->loadPackage($package, $repo->getRootAliases());
-                }
-            }
-
-            $packageNames = $newPackageNames;
-        } while (count($loadedMap) > $loadedCount);
-    }
-
     /**
      * Searches all packages providing the given package name and match the constraint
      *
@@ -181,44 +180,6 @@ class Pool
         return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName);
     }
 
-    private function loadPackage(PackageInterface $package, array $rootAliases, $acceptableExemption = false)
-    {
-        $names = $package->getNames();
-        $stability = $package->getStability();
-
-        if (!$acceptableExemption && !$this->isPackageAcceptable($names, $stability)) {
-            return;
-        }
-
-        $package->setId($this->id++);
-        $this->packages[] = $package;
-        $this->packageByExactName[$package->getName()][$package->id] = $package;
-
-        foreach ($names as $provided) {
-            $this->packageByName[$provided][] = $package;
-        }
-
-        // handle root package aliases
-        $name = $package->getName();
-        if (isset($rootAliases[$name][$package->getVersion()])) {
-            $alias = $rootAliases[$name][$package->getVersion()];
-            if ($package instanceof AliasPackage) {
-                $package = $package->getAliasOf();
-            }
-            $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
-            $aliasPackage->setRootPackageAlias(true);
-            $aliasPackage->setId($this->id++);
-
-            $package->getRepository()->addPackage($aliasPackage);
-            $this->packages[] = $aliasPackage;
-            $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
-
-            foreach ($aliasPackage->getNames() as $name) {
-                $this->packageByName[$name][] = $aliasPackage;
-            }
-        }
-    }
-
     /**
      * @see whatProvides
      */
@@ -226,12 +187,25 @@ class Pool
     {
         $candidates = array();
 
+        foreach ($this->providerRepos as $repo) {
+            foreach ($repo->whatProvides($this, $name) as $candidate) {
+                $candidates[] = $candidate;
+                if ($candidate->id < 1) {
+                    $candidate->setId($this->id++);
+                    $this->packages[$this->id - 2] = $candidate;
+                }
+            }
+        }
+
         if ($mustMatchName) {
+            $candidates = array_filter($candidates, function ($candidate) use ($name) {
+                return $candidate->getName() == $name;
+            });
             if (isset($this->packageByExactName[$name])) {
-                $candidates = $this->packageByExactName[$name];
+                $candidates = array_merge($candidates, $this->packageByExactName[$name]);
             }
         } elseif (isset($this->packageByName[$name])) {
-            $candidates = $this->packageByName[$name];
+            $candidates = array_merge($candidates, $this->packageByName[$name]);
         }
 
         $matches = $provideMatches = array();

+ 0 - 12
src/Composer/DependencyResolver/Solver.php

@@ -169,18 +169,6 @@ class Solver
         $this->jobs = $request->getJobs();
 
         $this->setupInstalledMap();
-
-        $packageNames = array();
-        foreach ($this->jobs as $job) {
-            switch ($job['cmd']) {
-                case 'install':
-                    $packageNames[$job['packageName']] = true;
-                    break;
-            }
-        }
-
-        $this->pool->loadRecursively(array_keys($packageNames));
-
         $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
         $this->checkForRootRequireProblems($ignorePlatformReqs);
         $this->decisions = new Decisions($this->pool);

+ 74 - 76
src/Composer/Repository/ComposerRepository.php

@@ -43,9 +43,10 @@ class ComposerRepository extends ArrayRepository
     protected $searchUrl;
     protected $hasProviders = false;
     protected $providersUrl;
-    protected $loadedMap = array();
     protected $lazyProvidersUrl;
     protected $providerListing;
+    protected $providers = array();
+    protected $providersByUid = array();
     protected $loader;
     protected $rootAliases;
     protected $allowSslDowngrade = false;
@@ -95,51 +96,6 @@ class ComposerRepository extends ArrayRepository
         $this->rootAliases = $rootAliases;
     }
 
-    public function getRootAliases()
-    {
-        return $this->rootAliases;
-    }
-
-    /**
-     * Load all packages with given names and dependencies
-     *
-     * @param array $packageNames
-     * @param callable|null $acceptableCallback Callback to filter packages
-     *
-     * @return array The loaded package objects
-     */
-    public function loadRecursively(array $packageNames, $acceptableCallback)
-    {
-        $workQueue = new \SplQueue;
-
-        foreach ($packageNames as $packageName) {
-            $workQueue->enqueue($packageName);
-        }
-
-        $loadedPackages = array();
-
-        while (!$workQueue->isEmpty()) {
-            $packageName = $workQueue->dequeue();
-            if (isset($this->loadedMap[$packageName])) {
-                continue;
-            }
-
-            $this->loadedMap[$packageName] = true;
-
-            $packages = $this->loadName($packageName, $acceptableCallback);
-
-            foreach ($packages as $package) {
-                $loadedPackages[] = $package;
-                $requires = $package->getRequires();
-                foreach ($requires as $link) {
-                    $workQueue->enqueue($link->getTarget());
-                }
-            }
-        }
-
-        return $loadedPackages;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -155,7 +111,7 @@ class ComposerRepository extends ArrayRepository
 
         foreach ($this->getProviderNames() as $providerName) {
             if ($name === $providerName) {
-                $packages = $this->loadName($providerName, null, false);
+                $packages = $this->whatProvides(new Pool('dev'), $providerName);
                 foreach ($packages as $package) {
                     if ($name == $package->getName() && $version === $package->getVersion()) {
                         return $package;
@@ -186,7 +142,7 @@ class ComposerRepository extends ArrayRepository
 
         foreach ($this->getProviderNames() as $providerName) {
             if ($name === $providerName) {
-                $packages = $this->loadName($providerName, null, false);
+                $packages = $this->whatProvides(new Pool('dev'), $providerName);
                 foreach ($packages as $package) {
                     if ($name == $package->getName() && (null === $version || $version === $package->getVersion())) {
                         $packages[] = $package;
@@ -284,17 +240,22 @@ class ComposerRepository extends ArrayRepository
         return $this->hasProviders;
     }
 
-    /**
-     * Loads package data for a given package name or provider name
-     *
-     * @param string $name
-     * @param callable|null $acceptableCallback A callback to check if a package should be loaded
-     * @param bool $exactMatch Whether packages only providing the name should be ignored
-     *
-     * @return array All packages that were loaded
-     */
-    protected function loadName($name, $acceptableCallback, $exactMatch = true)
+    public function resetPackageIds()
+    {
+        foreach ($this->providersByUid as $package) {
+            if ($package instanceof AliasPackage) {
+                $package->getAliasOf()->setId(-1);
+            }
+            $package->setId(-1);
+        }
+    }
+
+    public function whatProvides(Pool $pool, $name)
     {
+        if (isset($this->providers[$name])) {
+            return $this->providers[$name];
+        }
+
         // skip platform packages
         if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) {
             return array();
@@ -335,32 +296,69 @@ class ComposerRepository extends ArrayRepository
             $packages = $this->fetchFile($url, $cacheKey, $hash);
         }
 
-        $loadedPackages = array();
-        foreach ($packages['packages'] as $packageName => $versions) {
-            if ($exactMatch && $packageName !== $name) {
-                continue;
-            }
-
+        $this->providers[$name] = array();
+        foreach ($packages['packages'] as $versions) {
             foreach ($versions as $version) {
-                if ($acceptableCallback && !call_user_func(
-                    $acceptableCallback, strtolower($version['name']), VersionParser::parseStability($version['version'])
-                )) {
-                    continue;
-                }
+                // avoid loading the same objects twice
+                if (isset($this->providersByUid[$version['uid']])) {
+                    // skip if already assigned
+                    if (!isset($this->providers[$name][$version['uid']])) {
+                        // expand alias in two packages
+                        if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
+                            $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
+                            $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
+                        } else {
+                            $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
+                        }
+                        // check for root aliases
+                        if (isset($this->providersByUid[$version['uid'].'-root'])) {
+                            $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
+                        }
+                    }
+                } else {
+                    if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
+                        continue;
+                    }
+
+                    // load acceptable packages in the providers
+                    $package = $this->createPackage($version, 'Composer\Package\Package');
+                    $package->setRepository($this);
+
+                    if ($package instanceof AliasPackage) {
+                        $aliased = $package->getAliasOf();
+                        $aliased->setRepository($this);
 
-                // load acceptable packages in the providers
-                $package = $this->createPackage($version, 'Composer\Package\Package');
-                $this->addPackage($package);
+                        $this->providers[$name][$version['uid']] = $aliased;
+                        $this->providers[$name][$version['uid'].'-alias'] = $package;
 
-                $loadedPackages[] = $package;
+                        // override provider with its alias so it can be expanded in the if block above
+                        $this->providersByUid[$version['uid']] = $package;
+                    } else {
+                        $this->providers[$name][$version['uid']] = $package;
+                        $this->providersByUid[$version['uid']] = $package;
+                    }
+
+                    // handle root package aliases
+                    unset($rootAliasData);
+
+                    if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
+                        $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
+                    } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
+                        $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
+                    }
+
+                    if (isset($rootAliasData)) {
+                        $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
+                        $alias->setRepository($this);
 
-                if ($package instanceof AliasPackage) {
-                    $loadedPackages[] = $package->getAliasOf();
+                        $this->providers[$name][$version['uid'].'-root'] = $alias;
+                        $this->providersByUid[$version['uid'].'-root'] = $alias;
+                    }
                 }
             }
         }
 
-        return $loadedPackages;
+        return $this->providers[$name];
     }
 
     /**

+ 36 - 32
tests/Composer/Test/Repository/ComposerRepositoryTest.php

@@ -96,7 +96,7 @@ class ComposerRepositoryTest extends TestCase
         );
     }
 
-    public function testLoadRecursively()
+    public function testWhatProvides()
     {
         $repo = $this->getMockBuilder('Composer\Repository\ComposerRepository')
             ->disableOriginalConstructor()
@@ -124,41 +124,45 @@ class ComposerRepositoryTest extends TestCase
             ->method('fetchFile')
             ->will($this->returnValue(array(
                 'packages' => array(
-                    'a' => array(
-                        'dev-master' => array(
-                            'uid' => 1,
-                            'name' => 'a',
-                            'version' => 'dev-master',
-                            'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
-                        ),
-                        'dev-develop' => array(
-                            'uid' => 2,
-                            'name' => 'a',
-                            'version' => 'dev-develop',
-                            'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')),
-                        ),
-                        '0.6' => array(
-                            'uid' => 3,
-                            'name' => 'a',
-                            'version' => '0.6',
-                        ),
-                    ),
+                    array(array(
+                        'uid' => 1,
+                        'name' => 'a',
+                        'version' => 'dev-master',
+                        'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
+                    )),
+                    array(array(
+                        'uid' => 2,
+                        'name' => 'a',
+                        'version' => 'dev-develop',
+                        'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')),
+                    )),
+                    array(array(
+                        'uid' => 3,
+                        'name' => 'a',
+                        'version' => '0.6',
+                    )),
                 )
             )));
 
+        $pool = $this->getMock('Composer\DependencyResolver\Pool');
+        $pool->expects($this->any())
+            ->method('isPackageAcceptable')
+            ->will($this->returnValue(true));
+
         $versionParser = new VersionParser();
+        $repo->setRootAliases(array(
+            'a' => array(
+                $versionParser->normalize('0.6') => array('alias' => 'dev-feature', 'alias_normalized' => $versionParser->normalize('dev-feature')),
+                $versionParser->normalize('1.1.x-dev') => array('alias' => '1.0', 'alias_normalized' => $versionParser->normalize('1.0')),
+            ),
+        ));
+
+        $packages = $repo->whatProvides($pool, 'a');
 
-        $that = $this;
-        $packages = $repo->loadRecursively(array('a'), function ($name, $stability) use ($that) {
-            $that->assertEquals('a', $name);
-            return true;
-        });
-
-        $this->assertCount(5, $packages);
-        $this->assertEquals(array('1.0.x-dev', 'dev-master', '1.1.x-dev', 'dev-develop', '0.6'), array_map(function ($p) {
-            return $p->getPrettyVersion();
-        }, $packages));
-        $this->assertInstanceOf('Composer\Package\AliasPackage', $packages[2]);
-        $this->assertSame($packages[3], $packages[2]->getAliasOf());
+        $this->assertCount(7, $packages);
+        $this->assertEquals(array('1', '1-alias', '2', '2-alias', '2-root', '3', '3-root'), array_keys($packages));
+        $this->assertInstanceOf('Composer\Package\AliasPackage', $packages['2-root']);
+        $this->assertSame($packages['2'], $packages['2-root']->getAliasOf());
+        $this->assertSame($packages['2'], $packages['2-alias']->getAliasOf());
     }
 }