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

main
Jordi Boggiano 12 years ago
parent fde3477563
commit c0e5736ae7

@ -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) {

@ -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());
} }

@ -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);
} }

Loading…
Cancel
Save