From e50f78043ab6a983217814cc89e6a6744205ac3f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 15 Jan 2020 15:34:33 +0100 Subject: [PATCH 1/6] 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 +{ +} From 73bc137c3ca38b81e0b8ec0ee7437ce39aabd66e Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 15 Jan 2020 16:21:23 +0100 Subject: [PATCH 2/6] Avoid nameConstraints from being collected for fixed packages --- src/Composer/DependencyResolver/PoolBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index b150133d3..cb6a34947 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -52,6 +52,7 @@ 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) { + $this->nameConstraints[$package->getName()] = null; $this->loadedNames[$package->getName()] = true; unset($loadNames[$package->getName()]); $loadNames += $this->loadPackage($request, $package); From cc91e9164abd09f07f1e078aee54be66539c429d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 17 Jan 2020 13:54:13 +0100 Subject: [PATCH 3/6] Stop unrolling the root aliases --- src/Composer/DependencyResolver/Request.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index d0502c1c5..62418738f 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -48,10 +48,6 @@ class Request */ public function fixPackage(PackageInterface $package, $lockable = true) { - if ($package instanceof RootAliasPackage) { - $package = $package->getAliasOf(); - } - $this->fixedPackages[spl_object_hash($package)] = $package; if (!$lockable) { From 6f44350c0108c4310fe5e85cfac70fce46a33aa0 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 17 Jan 2020 14:01:01 +0100 Subject: [PATCH 4/6] Remove problem reporting for locked package not being found, needs to be fixed in #7779 later --- tests/Composer/Test/Fixtures/installer/solver-problems.test | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/Composer/Test/Fixtures/installer/solver-problems.test b/tests/Composer/Test/Fixtures/installer/solver-problems.test index 57d3ced92..7ca5b628f 100644 --- a/tests/Composer/Test/Fixtures/installer/solver-problems.test +++ b/tests/Composer/Test/Fixtures/installer/solver-problems.test @@ -61,12 +61,10 @@ Your requirements could not be resolved to an installable set of packages. Problem 2 - The requested package bogus/pkg could not be found in any version, there may be a typo in the package name. Problem 3 + - The requested package stable-requiree-excluded/pkg could not be found in any version, there may be a typo in the package name. + Problem 4 - Installation request for requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0]. - requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> no matching package found. - Problem 4 - - stable-requiree-excluded/pkg is locked to version 1.0.0 and an update of this package was not requested. - - Same name, can only install one of: stable-requiree-excluded/pkg[1.0.0, 1.0.1]. - - Installation request for stable-requiree-excluded/pkg 1.0.1 -> satisfiable by stable-requiree-excluded/pkg[1.0.1]. Potential causes: - A typo in the package name From 572ef1add1e9343eccaf7876f9d94d18c0fd26f4 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 17 Jan 2020 14:25:43 +0100 Subject: [PATCH 5/6] Add comment for lockable --- src/Composer/DependencyResolver/Request.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 62418738f..fc4a21070 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -45,6 +45,8 @@ class Request /** * Mark an existing package as being installed and having to remain installed + * + * @param bool $lockable if set to false, the package will not be written to the lock file */ public function fixPackage(PackageInterface $package, $lockable = true) { From 56b2e1ae7ae2335f7292d740a3004901fae7293f Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 17 Jan 2020 14:26:52 +0100 Subject: [PATCH 6/6] Allow installing an aliased root package --- src/Composer/Installer.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 9cba7f762..9f831ef8f 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -35,6 +35,7 @@ use Composer\Installer\NoopInstaller; use Composer\Installer\SuggestedPackagesReporter; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; +use Composer\Package\RootAliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompletePackage; use Composer\Package\Link; @@ -779,6 +780,9 @@ class Installer $request = new Request($lockedRepository); $request->fixPackage($rootPackage, false); + if ($rootPackage instanceof RootAliasPackage) { + $request->fixPackage($rootPackage->getAliasOf(), false); + } $fixedPackages = $platformRepo->getPackages(); if ($this->additionalFixedRepository) {