From 835a91532d82c880ce111077e5953a0aa82f933e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 30 Jan 2020 22:14:19 +0100 Subject: [PATCH] Add PRE_POOL_CREATE event, fixes #8348 --- doc/articles/scripts.md | 2 + .../DependencyResolver/PoolBuilder.php | 24 ++- src/Composer/Installer.php | 6 +- src/Composer/Plugin/PluginEvents.php | 11 ++ src/Composer/Plugin/PrePoolCreateEvent.php | 158 ++++++++++++++++++ src/Composer/Repository/RepositorySet.php | 5 +- 6 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 src/Composer/Plugin/PrePoolCreateEvent.php diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 751d3c492..c16977003 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -66,6 +66,8 @@ Composer fires the following named events during its execution process: - **pre-command-run**: occurs before a command is executed and allows you to manipulate the `InputInterface` object's options and arguments to tweak a command's behavior. +- **pre-pool-create**: occurs before the Pool of packages is created, and lets + you filter the list of packages which is going to enter the Solver. > **Note:** Composer makes no assumptions about the state of your dependencies > prior to `install` or `update`. Therefore, you should not specify scripts diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index 360924143..d3d14e629 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -21,6 +21,9 @@ use Composer\Repository\PlatformRepository; use Composer\Repository\RootPackageRepository; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\MultiConstraint; +use Composer\EventDispatcher\EventDispatcher; +use Composer\Plugin\PrePoolCreateEvent; +use Composer\Plugin\PluginEvents; /** * @author Nils Adermann @@ -31,6 +34,7 @@ class PoolBuilder private $stabilityFlags; private $rootAliases; private $rootReferences; + private $eventDispatcher; private $aliasMap = array(); private $nameConstraints = array(); @@ -38,12 +42,13 @@ class PoolBuilder private $packages = array(); private $unacceptableFixedPackages = array(); - public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences) + public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, EventDispatcher $eventDispatcher = null) { $this->acceptableStabilities = $acceptableStabilities; $this->stabilityFlags = $stabilityFlags; $this->rootAliases = $rootAliases; $this->rootReferences = $rootReferences; + $this->eventDispatcher = $eventDispatcher; } public function buildPool(array $repositories, Request $request) @@ -132,6 +137,23 @@ class PoolBuilder } } + if ($this->eventDispatcher) { + $prePoolCreateEvent = new PrePoolCreateEvent( + PluginEvents::PRE_POOL_CREATE, + $repositories, + $request, + $this->acceptableStabilities, + $this->stabilityFlags, + $this->rootAliases, + $this->rootReferences, + $this->packages, + $this->unacceptableFixedPackages + ); + $this->eventDispatcher->dispatch($prePoolCreateEvent->getName(), $prePoolCreateEvent); + $this->packages = $prePoolCreateEvent->getPackages(); + $this->unacceptableFixedPackages = $prePoolCreateEvent->getUnacceptableFixedPackages(); + } + $pool = new Pool($this->packages, $this->unacceptableFixedPackages); $this->aliasMap = array(); diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index dbd3de015..b7ee247db 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -381,7 +381,7 @@ class Installer } } - $pool = $repositorySet->createPool($request); + $pool = $repositorySet->createPool($request, $this->eventDispatcher); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $repositorySet, $pool, $request, $policy); // solve dependencies @@ -522,7 +522,7 @@ class Installer $request->requireName($link->getTarget(), $link->getConstraint()); } - $pool = $repositorySet->createPool($request); + $pool = $repositorySet->createPool($request, $this->eventDispatcher); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $repositorySet, $pool, $request, $policy); $solver = new Solver($policy, $pool, $this->io, $repositorySet); @@ -578,7 +578,7 @@ class Installer $request->requireName($link->getTarget(), $link->getConstraint()); } - $pool = $repositorySet->createPool($request); + $pool = $repositorySet->createPool($request, $this->eventDispatcher); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $repositorySet, $pool, $request, $policy); // solve dependencies diff --git a/src/Composer/Plugin/PluginEvents.php b/src/Composer/Plugin/PluginEvents.php index 1fb368baf..39cac6798 100644 --- a/src/Composer/Plugin/PluginEvents.php +++ b/src/Composer/Plugin/PluginEvents.php @@ -58,4 +58,15 @@ class PluginEvents * @var string */ const PRE_COMMAND_RUN = 'pre-command-run'; + + /** + * The PRE_POOL_CREATE event occurs before the Pool of packages is created, and lets + * you filter the list of packages which is going to enter the Solver + * + * The event listener method receives a + * Composer\Plugin\PrePoolCreateEvent instance. + * + * @var string + */ + const PRE_POOL_CREATE = 'pre-pool-create'; } diff --git a/src/Composer/Plugin/PrePoolCreateEvent.php b/src/Composer/Plugin/PrePoolCreateEvent.php new file mode 100644 index 000000000..0e6617739 --- /dev/null +++ b/src/Composer/Plugin/PrePoolCreateEvent.php @@ -0,0 +1,158 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Plugin; + +use Composer\EventDispatcher\Event; +use Symfony\Component\Console\Input\InputInterface; +use Composer\Repository\RepositoryInterface; +use Composer\DependencyResolver\Request; +use Composer\Package\PackageInterface; + +/** + * The pre command run event. + * + * @author Jordi Boggiano + */ +class PrePoolCreateEvent extends Event +{ + /** + * @var RepositoryInterface[] + */ + private $repositories; + /** + * @var Request + */ + private $request; + /** + * @var array + */ + private $acceptableStabilities; + /** + * @var array + */ + private $stabilityFlags; + /** + * @var array + */ + private $rootAliases; + /** + * @var array + */ + private $rootReferences; + /** + * @var PackageInterface[] + */ + private $packages; + /** + * @var PackageInterface[] + */ + private $unacceptableFixedPackages; + + /** + * @param string $name The event name + * @param RepositoryInterface[] $repositories + */ + public function __construct($name, array $repositories, Request $request, array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, array $packages, array $unacceptableFixedPackages) + { + parent::__construct($name); + + $this->repositories = $repositories; + $this->request = $request; + $this->acceptableStabilities = $acceptableStabilities; + $this->stabilityFlags = $stabilityFlags; + $this->rootAliases = $rootAliases; + $this->rootReferences = $rootReferences; + $this->packages = $packages; + $this->unacceptableFixedPackages = $unacceptableFixedPackages; + } + + /** + * @return RepositoryInterface[] + */ + public function getRepositories() + { + return $this->repositories; + } + + /** + * @return Request + */ + public function getRequest() + { + return $this->request; + } + + /** + * @return array + */ + public function getAcceptableStabilities() + { + return $this->acceptableStabilities; + } + + /** + * @return array + */ + public function getStabilityFlags() + { + return $this->stabilityFlags; + } + + /** + * @return array + */ + public function getRootAliases() + { + return $this->rootAliases; + } + + /** + * @return array + */ + public function getRootReferences() + { + return $this->rootReferences; + } + + /** + * @return PackageInterface[] + */ + public function getPackages() + { + return $this->packages; + } + + /** + * @return PackageInterface[] + */ + public function getUnacceptableFixedPackages() + { + return $this->unacceptableFixedPackages; + } + + /** + * @param PackageInterface[] $packages + */ + public function setPackages(array $packages) + { + $this->packages = $packages; + } + + /** + * @param PackageInterface[] $packages + */ + public function setUnacceptableFixedPackages(array $packages) + { + $this->unacceptableFixedPackages = $packages; + } +} diff --git a/src/Composer/Repository/RepositorySet.php b/src/Composer/Repository/RepositorySet.php index 80df9bb1d..6cafaa6c2 100644 --- a/src/Composer/Repository/RepositorySet.php +++ b/src/Composer/Repository/RepositorySet.php @@ -15,6 +15,7 @@ namespace Composer\Repository; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\PoolBuilder; use Composer\DependencyResolver\Request; +use Composer\EventDispatcher\EventDispatcher; use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Repository\CompositeRepository; @@ -188,9 +189,9 @@ class RepositorySet * * @return Pool */ - public function createPool(Request $request) + public function createPool(Request $request, EventDispatcher $eventDispatcher = null) { - $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences); + $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $eventDispatcher); foreach ($this->repositories as $repo) { if ($repo instanceof InstalledRepositoryInterface && !$this->allowInstalledRepositories) {