Просмотр исходного кода

Completely move loading of packages from composer repo to pool

Nils Adermann 10 лет назад
Родитель
Сommit
090711b21c

+ 66 - 37
src/Composer/DependencyResolver/Pool.php

@@ -102,42 +102,50 @@ class Pool
                 $repo->resetPackageIds();
             } else {
                 foreach ($repo->getPackages() as $package) {
-                    $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;
-                            }
-                        }
-                    }
+                    $this->loadPackage($package, $rootAliases, $exempt);
                 }
             }
         }
     }
 
+    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;
+            }
+        }
+    }
+
     public function getPriority(RepositoryInterface $repo)
     {
         $priority = array_search($repo, $this->repositories, true);
@@ -160,11 +168,32 @@ class Pool
         return $this->packages[$id - 1];
     }
 
-    public function ensureLoaded($constrainedNames)
+    public function loadRecursively(array $packageNames, $loadDev)
     {
-        foreach ($this->providerRepos as $repo) {
-            $repo->ensureLoaded($this, $constrainedNames);
-        }
+        $loadedMap = array();
+        do {
+            $newPackageNames = array();
+            $loadedCount = count($loadedMap);
+
+            foreach ($this->providerRepos as $repo) {
+                $packages = $repo->loadRecursively(
+                    $packageNames,
+                    $loadDev,
+                    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);
     }
 
     /**
@@ -193,7 +222,7 @@ class Pool
     private function computeWhatProvides($name, $constraint, $mustMatchName = false)
     {
         $candidates = array();
-
+/*
         foreach ($this->providerRepos as $repo) {
             foreach ($repo->whatProvides($this, $name) as $candidate) {
                 $candidates[] = $candidate;
@@ -202,7 +231,7 @@ class Pool
                     $this->packages[$this->id - 2] = $candidate;
                 }
             }
-        }
+        }*/
 
         if ($mustMatchName) {
             $candidates = array_filter($candidates, function ($candidate) use ($name) {

+ 3 - 6
src/Composer/DependencyResolver/Solver.php

@@ -170,19 +170,16 @@ class Solver
 
         $this->setupInstalledMap();
 
-        $constrainedNames = array();
+        $packageNames = array();
         foreach ($this->jobs as $job) {
             switch ($job['cmd']) {
                 case 'install':
-                    $constrainedNames[] = array(
-                        'name' => $job['packageName'],
-                        'constraint' => $job['constraint'],
-                    );
+                    $packageNames[] = $job['packageName'];
                     break;
             }
         }
 
-        $this->pool->ensureLoaded($constrainedNames);
+        $this->pool->loadRecursively($packageNames, true);
 
         $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
         $this->checkForRootRequireProblems($ignorePlatformReqs);

+ 36 - 93
src/Composer/Repository/ComposerRepository.php

@@ -43,10 +43,9 @@ 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;
@@ -96,38 +95,47 @@ class ComposerRepository extends ArrayRepository
         $this->rootAliases = $rootAliases;
     }
 
-    public function ensureLoaded($pool, array $constrainedNames)
+    public function getRootAliases()
+    {
+        return $this->rootAliases;
+    }
+
+    public function loadRecursively(array $packageNames, $loadDev, $acceptableCallback)
     {
         $workQueue = new \SplQueue;
 
-        foreach ($constrainedNames as $packageSpec) {
-            $workQueue->enqueue($packageSpec);
+        foreach ($packageNames as $packageName) {
+            $workQueue->enqueue($packageName);
         }
 
-        $loadedMap = array();
+        $loadedPackages = array();
 
         while (!$workQueue->isEmpty()) {
-            $packageSpec = $workQueue->dequeue();
-            if (isset($this->loadedMap[$packageSpec['name']])) {
+            $packageName = $workQueue->dequeue();
+            if (isset($this->loadedMap[$packageName])) {
                 continue;
             }
 
-            $this->loadedMap[$packageSpec['name']] = true;
+            $this->loadedMap[$packageName] = true;
 
-            $packages = $this->loadName($pool, $packageSpec['name']);
+            $packages = $this->loadName($packageName, $acceptableCallback);
 
             foreach ($packages as $package) {
-                foreach ($package->getRequires() as $link) {
-                    $workQueue->enqueue(array(
-                        'name' => $link->getTarget(),
-                        'constraint' => $link->getConstraint()
-                    ));
+                $loadedPackages[] = $package;
+                $requires = $package->getRequires();
+                if ($loadDev) {
+                    $requires = array_merge($requires, $package->getDevRequires());
+                }
+                foreach ($requires as $link) {
+                    $workQueue->enqueue($link->getTarget());
                 }
             }
         }
+
+        return $loadedPackages;
     }
 
-    protected function loadName($pool, $name)
+    protected function loadName($name, $acceptableCallback)
     {
         // skip platform packages
         if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) {
@@ -145,7 +153,6 @@ class ComposerRepository extends ArrayRepository
         } elseif ($this->providersUrl) {
             // package does not exist in this repo
             if (!isset($this->providerListing[$name])) {
-                $this->providers[$name] = array();
                 return array();
             }
 
@@ -158,7 +165,6 @@ class ComposerRepository extends ArrayRepository
 
             // package does not exist in this repo
             if (!isset($this->providerListing[$url])) {
-                $this->providers[$name] = array();
                 return array();
             }
             $hash = $this->providerListing[$url]['sha256'];
@@ -171,7 +177,6 @@ class ComposerRepository extends ArrayRepository
             $packages = $this->fetchFile($url, $cacheKey, $hash);
         }
 
-        $this->providers[$name] = array();
         $loadedPackages = array();
         foreach ($packages['packages'] as $versions) {
             foreach ($versions as $version) {
@@ -179,61 +184,21 @@ class ComposerRepository extends ArrayRepository
                     continue;
                 }
 
-                // avoid loading the same objects twice
-                if (isset($this->providersByUid[$version['uid']])) {
-                    /**
-                     * @todo verify and remove
-                     */
-                    throw new \RuntimeException("Should not happen anymore");
-                } 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);
-
-                    $loadedPackages[] = $package;
-
-                    if ($package instanceof AliasPackage) {
-                        $aliased = $package->getAliasOf();
-                        $aliased->setRepository($this);
-
-                        $loadedPackages[] = $aliased;
-
-                        foreach ($aliased->getNames() as $providedName) {
-                            $this->providers[$providedName][$version['uid']] = $aliased;
-                            $this->providers[$providedName][$version['uid'].'-alias'] = $package;
-                        }
-
-                        // override provider with its alias so it can be expanded in the if block above
-                        $this->providersByUid[$version['uid']] = $package;
-                    } else {
-                        foreach ($package->getNames() as $providedName) {
-                            $this->providers[$providedName][$version['uid']] = $package;
-                        }
-                        $this->providersByUid[$version['uid']] = $package;
-                    }
-
-                    // handle root package aliases
-                    unset($rootAliasData);
+                if (!$acceptableCallback(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
+                    continue;
+                }
 
-                    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()];
-                    }
+                // load acceptable packages in the providers
+                $package = $this->createPackage($version, 'Composer\Package\Package');
+                $package->setRepository($this);
 
-                    if (isset($rootAliasData)) {
-                        $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
-                        $alias->setRepository($this);
+                $loadedPackages[] = $package;
 
-                        $loadedPackages[] = $alias;
+                if ($package instanceof AliasPackage) {
+                    $aliased = $package->getAliasOf();
+                    $aliased->setRepository($this);
 
-                        $this->providers[$name][$version['uid'].'-root'] = $alias;
-                        $this->providersByUid[$version['uid'].'-root'] = $alias;
-                    }
+                    $loadedPackages[] = $aliased;
                 }
             }
         }
@@ -385,31 +350,9 @@ class ComposerRepository extends ArrayRepository
         return $this->hasProviders;
     }
 
-    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 || 'composer-plugin-api' === $name) {
-            return array();
-        }
-
-        /**
-         * @todo verify this is no longer possible and change code to remove this
-         */
-        throw new \RuntimeException("Could not find package that should have been loaded.");
+        throw new \RuntimeException("Runtime repository provider calculation no longer occurs");
     }
 
     /**