diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index de297ff39..cb6a34947 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,18 @@ 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->nameConstraints[$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 +74,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 +95,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 +130,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/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index d0502c1c5..fc4a21070 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -45,13 +45,11 @@ 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) { - if ($package instanceof RootAliasPackage) { - $package = $package->getAliasOf(); - } - $this->fixedPackages[spl_object_hash($package)] = $package; if (!$lockable) { diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 646bb4fcf..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; @@ -50,6 +51,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 +737,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); @@ -778,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) { 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 +{ +} 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