From e50f78043ab6a983217814cc89e6a6744205ac3f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 15 Jan 2020 15:34:33 +0100 Subject: [PATCH] Try to load packages from lock file only and avoid loading other versions for pinned packages --- .../DependencyResolver/PoolBuilder.php | 41 +++++-------------- src/Composer/Installer.php | 3 +- .../Repository/InstalledArrayRepository.php | 2 +- src/Composer/Repository/RepositorySet.php | 7 ++++ .../Repository/RootPackageRepository.php | 24 +++++++++++ 5 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 src/Composer/Repository/RootPackageRepository.php diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index de297ff39..b150133d3 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -16,8 +16,6 @@ use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Package; use Composer\Package\PackageInterface; -use Composer\Repository\ComposerRepository; -use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\MultiConstraint; @@ -54,13 +52,17 @@ class PoolBuilder // TODO do we really want the request here? kind of want a root requirements thingy instead $loadNames = array(); foreach ($request->getFixedPackages() as $package) { - // TODO can actually use very specific constraint - $loadNames[$package->getName()] = null; + $this->loadedNames[$package->getName()] = true; + unset($loadNames[$package->getName()]); + $loadNames += $this->loadPackage($request, $package); } foreach ($request->getJobs() as $job) { switch ($job['cmd']) { case 'install': + if (isset($this->loadedNames[$job['packageName']])) { + continue 2; + } // TODO currently lock above is always NULL if we adjust that, this needs to merge constraints // TODO does it really make sense that we can have install requests for the same package that is actively locked with non-matching constraints? // also see the solver-problems.test test case @@ -71,27 +73,16 @@ class PoolBuilder } } - // packages from the locked repository only get loaded if they are explicitly fixed - foreach ($repositories as $key => $repository) { - if ($repository === $request->getLockedRepository()) { - foreach ($repository->getPackages() as $lockedPackage) { - foreach ($request->getFixedPackages() as $package) { - if ($package === $lockedPackage) { - $loadNames += $this->loadPackage($request, $package, $key); - } - } - } - } - } - while (!empty($loadNames)) { foreach ($loadNames as $name => $void) { $this->loadedNames[$name] = true; } $newLoadNames = array(); - foreach ($repositories as $key => $repository) { - if ($repository instanceof PlatformRepository || $repository instanceof InstalledRepositoryInterface || $repository === $request->getLockedRepository()) { + foreach ($repositories as $repository) { + // these repos have their packages fixed if they need to be loaded so we + // never need to load anything else from them + if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) { continue; } @@ -103,9 +94,8 @@ class PoolBuilder unset($loadNames[$name]); } foreach ($result['packages'] as $package) { - if (call_user_func($this->isPackageAcceptableCallable, $package->getNames(), $package->getStability())) { - $newLoadNames += $this->loadPackage($request, $package, $key); + $newLoadNames += $this->loadPackage($request, $package); } } } @@ -139,15 +129,6 @@ class PoolBuilder } } - foreach ($repositories as $key => $repository) { - if ($repository instanceof PlatformRepository || - $repository instanceof InstalledRepositoryInterface) { - foreach ($repository->getPackages() as $package) { - $this->loadPackage($request, $package, $key); - } - } - } - $pool->setPackages($this->packages); unset($this->aliasMap); diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 646bb4fcf..9cba7f762 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -50,6 +50,7 @@ use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; use Composer\Repository\CompositeRepository; use Composer\Repository\InstalledArrayRepository; +use Composer\Repository\RootPackageRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; @@ -735,7 +736,7 @@ class Installer $this->fixedRootPackage->setDevRequires(array()); $repositorySet = new RepositorySet($rootAliases, $this->package->getReferences(), $minimumStability, $stabilityFlags, $rootRequires); - $repositorySet->addRepository(new InstalledArrayRepository(array($this->fixedRootPackage))); + $repositorySet->addRepository(new RootPackageRepository(array($this->fixedRootPackage))); $repositorySet->addRepository($platformRepo); if ($this->additionalFixedRepository) { $repositorySet->addRepository($this->additionalFixedRepository); diff --git a/src/Composer/Repository/InstalledArrayRepository.php b/src/Composer/Repository/InstalledArrayRepository.php index c801d49ea..7ad05d0fa 100644 --- a/src/Composer/Repository/InstalledArrayRepository.php +++ b/src/Composer/Repository/InstalledArrayRepository.php @@ -15,7 +15,7 @@ namespace Composer\Repository; /** * Installed array repository. * - * This is used for serving the RootPackage inside an in-memory InstalledRepository + * This is used as an in-memory InstalledRepository mostly for testing purposes * * @author Jordi Boggiano */ diff --git a/src/Composer/Repository/RepositorySet.php b/src/Composer/Repository/RepositorySet.php index 9b15a0115..5ffffb73d 100644 --- a/src/Composer/Repository/RepositorySet.php +++ b/src/Composer/Repository/RepositorySet.php @@ -20,6 +20,7 @@ use Composer\Package\Version\VersionParser; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\LockArrayRepository; +use Composer\Repository\InstalledRepositoryInterface; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Test\DependencyResolver\PoolTest; @@ -147,6 +148,12 @@ class RepositorySet { $poolBuilder = new PoolBuilder(array($this, 'isPackageAcceptable'), $this->rootRequires); + foreach ($this->repositories as $repo) { + if ($repo instanceof InstalledRepositoryInterface) { + throw new \LogicException('The pool can not accept packages from an installed repository'); + } + } + return $this->pool = $poolBuilder->buildPool($this->repositories, $this->rootAliases, $this->rootReferences, $request); } diff --git a/src/Composer/Repository/RootPackageRepository.php b/src/Composer/Repository/RootPackageRepository.php new file mode 100644 index 000000000..8b5892717 --- /dev/null +++ b/src/Composer/Repository/RootPackageRepository.php @@ -0,0 +1,24 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +/** + * Root package repository. + * + * This is used for serving the RootPackage inside an in-memory InstalledRepository + * + * @author Jordi Boggiano + */ +class RootPackageRepository extends ArrayRepository +{ +}