فهرست منبع

Add support for one-file-per-provider composer repositories

Jordi Boggiano 12 سال پیش
والد
کامیت
c0e5736ae7
3فایلهای تغییر یافته به همراه107 افزوده شده و 15 حذف شده
  1. 32 13
      src/Composer/DependencyResolver/Pool.php
  2. 1 1
      src/Composer/Json/JsonFile.php
  3. 74 1
      src/Composer/Repository/ComposerRepository.php

+ 32 - 13
src/Composer/DependencyResolver/Pool.php

@@ -20,6 +20,7 @@ use Composer\Package\LinkConstraint\LinkConstraintInterface;
 use Composer\Package\LinkConstraint\VersionConstraint;
 use Composer\Package\LinkConstraint\VersionConstraint;
 use Composer\Repository\RepositoryInterface;
 use Composer\Repository\RepositoryInterface;
 use Composer\Repository\CompositeRepository;
 use Composer\Repository\CompositeRepository;
+use Composer\Repository\ComposerRepository;
 use Composer\Repository\InstalledRepositoryInterface;
 use Composer\Repository\InstalledRepositoryInterface;
 use Composer\Repository\StreamableRepositoryInterface;
 use Composer\Repository\StreamableRepositoryInterface;
 use Composer\Repository\PlatformRepository;
 use Composer\Repository\PlatformRepository;
@@ -39,11 +40,13 @@ class Pool
     const MATCH_REPLACE = 3;
     const MATCH_REPLACE = 3;
 
 
     protected $repositories = array();
     protected $repositories = array();
+    protected $composerRepos = array();
     protected $packages = array();
     protected $packages = array();
     protected $packageByName = array();
     protected $packageByName = array();
     protected $acceptableStabilities;
     protected $acceptableStabilities;
     protected $stabilityFlags;
     protected $stabilityFlags;
     protected $versionParser;
     protected $versionParser;
+    protected $id = 1;
 
 
     public function __construct($minimumStability = 'stable', array $stabilityFlags = array())
     public function __construct($minimumStability = 'stable', array $stabilityFlags = array())
     {
     {
@@ -72,18 +75,20 @@ class Pool
             $repos = array($repo);
             $repos = array($repo);
         }
         }
 
 
-        $id = count($this->packages) + 1;
         foreach ($repos as $repo) {
         foreach ($repos as $repo) {
             $this->repositories[] = $repo;
             $this->repositories[] = $repo;
 
 
             $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
             $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
-            if ($repo instanceof StreamableRepositoryInterface) {
+
+            if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
+                $this->composerRepos[] = $repo;
+            } elseif ($repo instanceof StreamableRepositoryInterface) {
                 foreach ($repo->getMinimalPackages() as $package) {
                 foreach ($repo->getMinimalPackages() as $package) {
                     $name = $package['name'];
                     $name = $package['name'];
                     $version = $package['version'];
                     $version = $package['version'];
                     $stability = VersionParser::parseStability($version);
                     $stability = VersionParser::parseStability($version);
                     if ($exempt || $this->isPackageAcceptable($name, $stability)) {
                     if ($exempt || $this->isPackageAcceptable($name, $stability)) {
-                        $package['id'] = $id++;
+                        $package['id'] = $this->id++;
                         $this->packages[] = $package;
                         $this->packages[] = $package;
 
 
                         // collect names
                         // collect names
@@ -102,7 +107,7 @@ class Pool
                         }
                         }
 
 
                         foreach (array_keys($names) as $provided) {
                         foreach (array_keys($names) as $provided) {
-                            $this->packageByName[$provided][] =& $this->packages[$id-2];
+                            $this->packageByName[$provided][] =& $this->packages[$this->id - 2];
                         }
                         }
 
 
                         // handle root package aliases
                         // handle root package aliases
@@ -119,12 +124,12 @@ class Pool
                             $alias['version'] = $rootAliasData['alias_normalized'];
                             $alias['version'] = $rootAliasData['alias_normalized'];
                             $alias['alias'] = $rootAliasData['alias'];
                             $alias['alias'] = $rootAliasData['alias'];
                             $alias['alias_of'] = $package['id'];
                             $alias['alias_of'] = $package['id'];
-                            $alias['id'] = $id++;
+                            $alias['id'] = $this->id++;
                             $alias['root_alias'] = true;
                             $alias['root_alias'] = true;
                             $this->packages[] = $alias;
                             $this->packages[] = $alias;
 
 
                             foreach (array_keys($names) as $name) {
                             foreach (array_keys($names) as $name) {
-                                $this->packageByName[$name][] =& $this->packages[$id-2];
+                                $this->packageByName[$name][] =& $this->packages[$this->id - 2];
                             }
                             }
                         }
                         }
 
 
@@ -135,11 +140,11 @@ class Pool
                             $alias['version'] = $package['alias_normalized'];
                             $alias['version'] = $package['alias_normalized'];
                             $alias['alias'] = $package['alias'];
                             $alias['alias'] = $package['alias'];
                             $alias['alias_of'] = $package['id'];
                             $alias['alias_of'] = $package['id'];
-                            $alias['id'] = $id++;
+                            $alias['id'] = $this->id++;
                             $this->packages[] = $alias;
                             $this->packages[] = $alias;
 
 
                             foreach (array_keys($names) as $name) {
                             foreach (array_keys($names) as $name) {
-                                $this->packageByName[$name][] =& $this->packages[$id-2];
+                                $this->packageByName[$name][] =& $this->packages[$this->id - 2];
                             }
                             }
                         }
                         }
                     }
                     }
@@ -149,7 +154,7 @@ class Pool
                     $name = $package->getName();
                     $name = $package->getName();
                     $stability = $package->getStability();
                     $stability = $package->getStability();
                     if ($exempt || $this->isPackageAcceptable($name, $stability)) {
                     if ($exempt || $this->isPackageAcceptable($name, $stability)) {
-                        $package->setId($id++);
+                        $package->setId($this->id++);
                         $this->packages[] = $package;
                         $this->packages[] = $package;
 
 
                         foreach ($package->getNames() as $name) {
                         foreach ($package->getNames() as $name) {
@@ -163,7 +168,7 @@ class Pool
                             $package->setPrettyAlias($alias['alias']);
                             $package->setPrettyAlias($alias['alias']);
                             $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
                             $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
                             $aliasPackage->setRootPackageAlias(true);
                             $aliasPackage->setRootPackageAlias(true);
-                            $aliasPackage->setId($id++);
+                            $aliasPackage->setId($this->id++);
 
 
                             $this->packages[] = $aliasPackage;
                             $this->packages[] = $aliasPackage;
 
 
@@ -208,7 +213,7 @@ class Pool
     */
     */
     public function getMaxId()
     public function getMaxId()
     {
     {
-        return count($this->packages);
+        return $this->id - 1;
     }
     }
 
 
     /**
     /**
@@ -221,11 +226,25 @@ class Pool
      */
      */
     public function whatProvides($name, LinkConstraintInterface $constraint = null)
     public function whatProvides($name, LinkConstraintInterface $constraint = null)
     {
     {
-        if (!isset($this->packageByName[$name])) {
+        $candidates = array();
+
+        foreach ($this->composerRepos as $repo) {
+            foreach ($repo->whatProvides($name) as $candidate) {
+                $candidates[] = $candidate;
+                if ($candidate->getId() < 1) {
+                    $candidate->setId($this->id++);
+                    $this->packages[$candidate->getId()] = $candidate;
+                }
+            }
+        }
+
+        if (!isset($this->packageByName[$name]) && !$candidates) {
             return array();
             return array();
         }
         }
 
 
-        $candidates = $this->packageByName[$name];
+        if (isset($this->packageByName[$name])) {
+            $candidates = array_merge($candidates, $this->packageByName[$name]);
+        }
 
 
         if (null === $constraint) {
         if (null === $constraint) {
             foreach ($candidates as $key => $candidate) {
             foreach ($candidates as $key => $candidate) {

+ 1 - 1
src/Composer/Json/JsonFile.php

@@ -85,7 +85,7 @@ class JsonFile
                 $json = file_get_contents($this->path);
                 $json = file_get_contents($this->path);
             }
             }
         } catch (TransportException $e) {
         } catch (TransportException $e) {
-            throw new \RuntimeException($e->getMessage());
+            throw new \RuntimeException($e->getMessage(), 0, $e);
         } catch (\Exception $e) {
         } catch (\Exception $e) {
             throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
             throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
         }
         }

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

@@ -20,6 +20,7 @@ use Composer\Cache;
 use Composer\Config;
 use Composer\Config;
 use Composer\IO\IOInterface;
 use Composer\IO\IOInterface;
 use Composer\Util\RemoteFilesystem;
 use Composer\Util\RemoteFilesystem;
+use Composer\Downloader\TransportException;
 
 
 /**
 /**
  * @author Jordi Boggiano <j.boggiano@seld.be>
  * @author Jordi Boggiano <j.boggiano@seld.be>
@@ -32,10 +33,14 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
     protected $io;
     protected $io;
     protected $cache;
     protected $cache;
     protected $notifyUrl;
     protected $notifyUrl;
+    protected $providersUrl;
+    protected $providers = array();
+    protected $providersByUid = array();
     protected $loader;
     protected $loader;
     private $rawData;
     private $rawData;
     private $minimalPackages;
     private $minimalPackages;
     private $degradedMode = false;
     private $degradedMode = false;
+    private $rootData;
 
 
     public function __construct(array $repoConfig, IOInterface $io, Config $config)
     public function __construct(array $repoConfig, IOInterface $io, Config $config)
     {
     {
@@ -182,6 +187,55 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
         return $aliasPackage;
         return $aliasPackage;
     }
     }
 
 
+    public function hasProviders()
+    {
+        $this->loadRootServerFile();
+
+        return null !== $this->providersUrl;
+    }
+
+    public function whatProvides($name)
+    {
+        if (isset($this->providers[$name])) {
+            return $this->providers[$name];
+        }
+
+        $url = str_replace('%package%', strtolower($name), $this->providersUrl);
+
+        try {
+            $json = new JsonFile($url, new RemoteFilesystem($this->io));
+            $packages = $json->read();
+        } catch (\RuntimeException $e) {
+            if (!$e->getPrevious() instanceof TransportException || $e->getPrevious()->getCode() !== 404) {
+                throw $e;
+            }
+        }
+
+        $this->providers[$name] = array();
+        foreach ($packages['packages'] as $name => $versions) {
+            foreach ($versions as $version) {
+                if (isset($this->providersByUid[$version['uid']])) {
+                    $this->providers[$name][] = $this->providersByUid[$version['uid']];
+                } else {
+                    $package = $this->createPackage($version, 'Composer\Package\Package');
+                    $package->setRepository($this);
+
+                    $this->providers[$name][] = $package;
+                    $this->providersByUid[$version['uid']] = $package;
+
+                    if ($package->getAlias()) {
+                        $alias = $this->createAliasPackage($package);
+
+                        $this->providers[$name][] = $alias;
+                        $this->providersByUid[$version['uid']] = $alias;
+                    }
+                }
+            }
+        }
+
+        return $this->providers[$name];
+    }
+
     /**
     /**
      * {@inheritDoc}
      * {@inheritDoc}
      */
      */
@@ -196,8 +250,12 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
         }
         }
     }
     }
 
 
-    protected function loadDataFromServer()
+    protected function loadRootServerFile()
     {
     {
+        if (null !== $this->rootData) {
+            return $this->rootData;
+        }
+
         if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
         if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
             throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
             throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
         }
         }
@@ -220,6 +278,21 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
             }
             }
         }
         }
 
 
+        if (!empty($data['providers'])) {
+            if ('/' === $data['providers'][0]) {
+                $this->providersUrl = preg_replace('{(https?://[^/]+).*}i', '$1' . $data['providers'], $this->url);
+            } else {
+                $this->providersUrl = $data['providers'];
+            }
+        }
+
+        return $this->rootData = $data;
+    }
+
+    protected function loadDataFromServer()
+    {
+        $data = $this->loadRootServerFile();
+
         return $this->loadIncludes($data);
         return $this->loadIncludes($data);
     }
     }