From 9b24734c9d4f2b3d8df4229f4fe05b73c11d2155 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 22 Oct 2011 22:20:30 +0200 Subject: [PATCH] Add parsing and on-the-fly loading of repositories defined in packages --- src/Composer/Package/Dumper/ArrayDumper.php | 1 + src/Composer/Package/Loader/ArrayLoader.php | 17 ++++++++- src/Composer/Package/MemoryPackage.php | 19 ++++++++++ src/Composer/Package/PackageInterface.php | 9 +++++ src/Composer/Repository/ArrayRepository.php | 26 +++++++------- .../Repository/ComposerRepository.php | 2 +- .../Repository/RepositoryInterface.php | 7 ++++ src/Composer/Repository/RepositoryManager.php | 35 +++++++++++++++---- 8 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/Composer/Package/Dumper/ArrayDumper.php b/src/Composer/Package/Dumper/ArrayDumper.php index 58c7c3f50..66aad1606 100644 --- a/src/Composer/Package/Dumper/ArrayDumper.php +++ b/src/Composer/Package/Dumper/ArrayDumper.php @@ -40,6 +40,7 @@ class ArrayDumper 'recommends', 'suggests', 'autoload', + 'repositories', ); $data = array(); diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 3c43649db..2a2d3bb75 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -13,6 +13,7 @@ namespace Composer\Package\Loader; use Composer\Package; +use Composer\Repository\RepositoryManager; /** * @author Konstantin Kudryashiv @@ -30,9 +31,11 @@ class ArrayLoader ); protected $versionParser; + private $manager; - public function __construct($parser = null) + public function __construct(RepositoryManager $manager, $parser = null) { + $this->manager = $manager; $this->versionParser = $parser; if (!$parser) { $this->versionParser = new Package\Version\VersionParser; @@ -50,6 +53,18 @@ class ArrayLoader $package->setTargetDir($config['target-dir']); } + if (isset($config['repositories'])) { + $repositories = array(); + foreach ($config['repositories'] as $repo) { + if (!$repo) { + continue; + } + $repository = $this->manager->createRepository(key($repo), current($repo)); + $this->manager->addRepository($repository); + } + $package->setRepositories($config['repositories']); + } + if (isset($config['extra'])) { $package->setExtra($config['extra']); } diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index 2eea5c2b0..946cdb55b 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/src/Composer/Package/MemoryPackage.php @@ -31,6 +31,7 @@ class MemoryPackage extends BasePackage protected $distSha1Checksum; protected $releaseType; protected $version; + protected $repositories; protected $license; protected $extra = array(); @@ -233,6 +234,24 @@ class MemoryPackage extends BasePackage return $this->distSha1Checksum; } + /** + * Set the repositories + * + * @param string $repositories + */ + public function setRepositories($repositories) + { + $this->repositories = $repositories; + } + + /** + * {@inheritDoc} + */ + public function getRepositories() + { + return $this->repositories; + } + /** * Set the release type * diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index 1bad85f51..02f619689 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -228,6 +228,15 @@ interface PackageInterface */ function getAutoload(); + /** + * Returns an array of repositories + * + * {"": {}} + * + * @return array Repositories + */ + function getRepositories(); + /** * Stores a reference to the repository that owns the package * diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 153f87caa..e76e718fc 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -22,14 +22,10 @@ use Composer\Package\PackageInterface; class ArrayRepository implements RepositoryInterface { protected $packages; + protected $repositoryManager; /** - * Searches for a package by it's name and version (if has one). - * - * @param string $name package name - * @param string $version package version - * - * @return PackageInterface|null + * {@inheritDoc} */ public function findPackage($name, $version) { @@ -41,11 +37,15 @@ class ArrayRepository implements RepositoryInterface } /** - * Checks if specified package in this repository. - * - * @param PackageInterface $package package instance - * - * @return Boolean + * {@inheritDoc} + */ + public function setRepositoryManager(RepositoryManager $manager) + { + $this->repositoryManager = $manager; + } + + /** + * {@inheritDoc} */ public function hasPackage(PackageInterface $package) { @@ -93,9 +93,7 @@ class ArrayRepository implements RepositoryInterface } /** - * Returns all contained packages - * - * @return array All packages + * {@inheritDoc} */ public function getPackages() { diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 81ecc005c..630f726ea 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -51,7 +51,7 @@ class ComposerRepository extends ArrayRepository private function createPackages($data) { foreach ($data['versions'] as $rev) { - $loader = new ArrayLoader(); + $loader = new ArrayLoader($this->repositoryManager); $this->addPackage($loader->load($rev)); } } diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index a94ecea4c..609aed2fb 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -47,4 +47,11 @@ interface RepositoryInterface extends \Countable * @return array */ function getPackages(); + + /** + * Stores the RepositoryManager owning this repository + * + * @param RepositoryManager $manager + */ + function setRepositoryManager(RepositoryManager $manager); } diff --git a/src/Composer/Repository/RepositoryManager.php b/src/Composer/Repository/RepositoryManager.php index dc7766cfa..c53d71122 100644 --- a/src/Composer/Repository/RepositoryManager.php +++ b/src/Composer/Repository/RepositoryManager.php @@ -24,6 +24,15 @@ class RepositoryManager private $repositories = array(); private $repositoryClasses = array(); + /** + * Used for lazy loading of packages and their contained repositories + * + * This is a performance optimization to avoid loading all packages unless they are needed + * + * @var Boolean + */ + private $initialized; + /** * Searches for a package by it's name and version in managed repositories. * @@ -49,24 +58,31 @@ class RepositoryManager public function addRepository(RepositoryInterface $repository) { $this->repositories[] = $repository; + + $repository->setRepositoryManager($this); + + // already initialized, so initialize new repos on the fly + if ($this->initialized) { + $repository->getPackages(); + } } /** - * Returns repository class for a specific installation type. - * - * @param string $type installation type + * Returns a new repository for a specific installation type. * + * @param string $type repository type + * @param string $config repository configuration * @return RepositoryInterface - * * @throws InvalidArgumentException if repository for provided type is not registeterd */ - public function getRepositoryClass($type) + public function createRepository($type, $config) { if (!isset($this->repositoryClasses[$type])) { throw new \InvalidArgumentException('Repository type is not registered: '.$type); } - return $this->repositoryClasses[$type]; + $class = $this->repositoryClasses[$type]; + return new $class($config); } /** @@ -87,6 +103,13 @@ class RepositoryManager */ public function getRepositories() { + if (!$this->initialized) { + $this->initialized = true; + // warm up repos to be sure all sub-repos are added before we return + foreach ($this->repositories as $repository) { + $repository->getPackages(); + } + } return $this->repositories; }