Try to load packages from lock file only and avoid loading other versions for pinned packages

main
Jordi Boggiano 5 years ago
parent de189c1b80
commit e50f78043a
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC

@ -16,8 +16,6 @@ use Composer\Package\AliasPackage;
use Composer\Package\BasePackage; use Composer\Package\BasePackage;
use Composer\Package\Package; use Composer\Package\Package;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\MultiConstraint; 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 // TODO do we really want the request here? kind of want a root requirements thingy instead
$loadNames = array(); $loadNames = array();
foreach ($request->getFixedPackages() as $package) { foreach ($request->getFixedPackages() as $package) {
// TODO can actually use very specific constraint $this->loadedNames[$package->getName()] = true;
$loadNames[$package->getName()] = null; unset($loadNames[$package->getName()]);
$loadNames += $this->loadPackage($request, $package);
} }
foreach ($request->getJobs() as $job) { foreach ($request->getJobs() as $job) {
switch ($job['cmd']) { switch ($job['cmd']) {
case 'install': 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 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? // 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 // 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)) { while (!empty($loadNames)) {
foreach ($loadNames as $name => $void) { foreach ($loadNames as $name => $void) {
$this->loadedNames[$name] = true; $this->loadedNames[$name] = true;
} }
$newLoadNames = array(); $newLoadNames = array();
foreach ($repositories as $key => $repository) { foreach ($repositories as $repository) {
if ($repository instanceof PlatformRepository || $repository instanceof InstalledRepositoryInterface || $repository === $request->getLockedRepository()) { // 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; continue;
} }
@ -103,9 +94,8 @@ class PoolBuilder
unset($loadNames[$name]); unset($loadNames[$name]);
} }
foreach ($result['packages'] as $package) { foreach ($result['packages'] as $package) {
if (call_user_func($this->isPackageAcceptableCallable, $package->getNames(), $package->getStability())) { 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); $pool->setPackages($this->packages);
unset($this->aliasMap); unset($this->aliasMap);

@ -50,6 +50,7 @@ use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface; use Composer\Package\RootPackageInterface;
use Composer\Repository\CompositeRepository; use Composer\Repository\CompositeRepository;
use Composer\Repository\InstalledArrayRepository; use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\RootPackageRepository;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryManager; use Composer\Repository\RepositoryManager;
@ -735,7 +736,7 @@ class Installer
$this->fixedRootPackage->setDevRequires(array()); $this->fixedRootPackage->setDevRequires(array());
$repositorySet = new RepositorySet($rootAliases, $this->package->getReferences(), $minimumStability, $stabilityFlags, $rootRequires); $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); $repositorySet->addRepository($platformRepo);
if ($this->additionalFixedRepository) { if ($this->additionalFixedRepository) {
$repositorySet->addRepository($this->additionalFixedRepository); $repositorySet->addRepository($this->additionalFixedRepository);

@ -15,7 +15,7 @@ namespace Composer\Repository;
/** /**
* Installed array 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 <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
*/ */

@ -20,6 +20,7 @@ use Composer\Package\Version\VersionParser;
use Composer\Repository\CompositeRepository; use Composer\Repository\CompositeRepository;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Repository\LockArrayRepository; use Composer\Repository\LockArrayRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Test\DependencyResolver\PoolTest; use Composer\Test\DependencyResolver\PoolTest;
@ -147,6 +148,12 @@ class RepositorySet
{ {
$poolBuilder = new PoolBuilder(array($this, 'isPackageAcceptable'), $this->rootRequires); $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); return $this->pool = $poolBuilder->buildPool($this->repositories, $this->rootAliases, $this->rootReferences, $request);
} }

@ -0,0 +1,24 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* 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 <j.boggiano@seld.be>
*/
class RootPackageRepository extends ArrayRepository
{
}
Loading…
Cancel
Save