From c0f19f6c573550916373fbaae7245558ffb75af6 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Wed, 12 Sep 2018 11:49:09 +0200 Subject: [PATCH] Move construction of pool from repo set into a pool builder Pool construction depends on the install request now, so only required packages get loaded, add some structure for future asynchronously loading composer repositories --- .../DependencyResolver/DefaultPolicy.php | 11 +- src/Composer/DependencyResolver/Pool.php | 119 ++------------ .../DependencyResolver/PoolBuilder.php | 147 ++++++++++++++++++ src/Composer/DependencyResolver/Problem.php | 4 +- src/Composer/DependencyResolver/Rule.php | 15 +- src/Composer/DependencyResolver/Solver.php | 2 +- .../SolverProblemsException.php | 6 +- src/Composer/Installer.php | 4 +- src/Composer/Package/Locker.php | 4 +- .../Repository/AsyncRepositoryInterface.php | 38 +++++ src/Composer/Repository/BaseRepository.php | 15 ++ .../Repository/LockArrayRepository.php | 25 +++ .../Repository/RepositoryInterface.php | 9 ++ src/Composer/Repository/RepositorySet.php | 41 +++-- .../DependencyResolver/DefaultPolicyTest.php | 31 ++-- .../Test/DependencyResolver/PoolTest.php | 79 +--------- .../Test/DependencyResolver/RuleSetTest.php | 17 +- .../Test/DependencyResolver/RuleTest.php | 20 +-- .../Test/DependencyResolver/SolverTest.php | 19 ++- tests/Composer/Test/InstallerTest.php | 1 - 20 files changed, 358 insertions(+), 249 deletions(-) create mode 100644 src/Composer/DependencyResolver/PoolBuilder.php create mode 100644 src/Composer/Repository/AsyncRepositoryInterface.php create mode 100644 src/Composer/Repository/LockArrayRepository.php diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 542c6e625..051bc7449 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -57,11 +57,6 @@ class DefaultPolicy implements PolicyInterface return $packages; } - public function getPriority(Pool $pool, PackageInterface $package) - { - return $pool->getPriority($package->getRepository()); - } - public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null) { $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals); @@ -168,7 +163,7 @@ class DefaultPolicy implements PolicyInterface return 1; } - return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1; + return ($pool->getPriority($a->id) > $pool->getPriority($b->id)) ? -1 : 1; } /** @@ -236,10 +231,10 @@ class DefaultPolicy implements PolicyInterface } if (null === $priority) { - $priority = $this->getPriority($pool, $package); + $priority = $pool->getPriority($package->id); } - if ($this->getPriority($pool, $package) != $priority) { + if ($pool->getPriority($package->id) != $priority) { break; } diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index ee4bace97..6ad4d9f31 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -27,7 +27,7 @@ use Composer\Repository\PlatformRepository; use Composer\Package\PackageInterface; /** - * A package pool contains repositories that provide packages. + * A package pool contains all packages for dependency resolution * * @author Nils Adermann * @author Jordi Boggiano @@ -41,23 +41,18 @@ class Pool implements \Countable const MATCH_REPLACE = 3; const MATCH_FILTERED = 4; - protected $repositories = array(); protected $providerRepos = array(); protected $packages = array(); protected $packageByName = array(); protected $packageByExactName = array(); - protected $acceptableStabilities; - protected $stabilityFlags; + protected $priorities = array(); protected $versionParser; protected $providerCache = array(); protected $filterRequires; protected $whitelist = null; - protected $id = 1; - public function __construct(array $acceptableStabilities, array $stabilityFlags = array(), array $filterRequires = array()) + public function __construct(array $filterRequires = array()) { - $this->acceptableStabilities = $acceptableStabilities; - $this->stabilityFlags = $stabilityFlags; $this->filterRequires = $filterRequires; $this->versionParser = new VersionParser; } @@ -68,76 +63,24 @@ class Pool implements \Countable $this->providerCache = array(); } - /** - * Adds a repository and its packages to this package pool - * - * @param RepositoryInterface $repo A package repository - * @param array $rootAliases - */ - public function addRepository(RepositoryInterface $repo, $rootAliases = array()) + public function setPackages(array $packages, array $priorities = array()) { - if ($repo instanceof CompositeRepository) { - $repos = $repo->getRepositories(); - } else { - $repos = array($repo); - } + $this->priorities = $priorities; + $this->packages = $packages; - foreach ($repos as $repo) { - $this->repositories[] = $repo; - - $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface; - - if ($repo instanceof ComposerRepository && $repo->hasProviders()) { - $this->providerRepos[] = $repo; - $repo->setRootAliases($rootAliases); - $repo->resetPackageIds(); - } else { - foreach ($repo->getPackages() as $package) { - $names = $package->getNames(); - $stability = $package->getStability(); - if ($exempt || $this->isPackageAcceptable($names, $stability)) { - $package->setId($this->id++); - $this->packages[] = $package; - $this->packageByExactName[$package->getName()][$package->id] = $package; - - foreach ($names as $provided) { - $this->packageByName[$provided][] = $package; - } - - // handle root package aliases - $name = $package->getName(); - if (isset($rootAliases[$name][$package->getVersion()])) { - $alias = $rootAliases[$name][$package->getVersion()]; - if ($package instanceof AliasPackage) { - $package = $package->getAliasOf(); - } - $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']); - $aliasPackage->setRootPackageAlias(true); - $aliasPackage->setId($this->id++); - - $package->getRepository()->addPackage($aliasPackage); - $this->packages[] = $aliasPackage; - $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage; - - foreach ($aliasPackage->getNames() as $name) { - $this->packageByName[$name][] = $aliasPackage; - } - } - } - } + foreach ($this->packages as $package) { + $names = $package->getNames(); + $this->packageByExactName[$package->getName()][$package->id] = $package; + + foreach ($names as $provided) { + $this->packageByName[$provided][] = $package; } } } - public function getPriority(RepositoryInterface $repo) + public function getPriority($id) { - $priority = array_search($repo, $this->repositories, true); - - if (false === $priority) { - throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool."); - } - - return -$priority; + return $this->priorities[$id - 1]; } /** @@ -191,25 +134,12 @@ class Pool implements \Countable { $candidates = array(); - foreach ($this->providerRepos as $repo) { - foreach ($repo->whatProvides($name, $bypassFilters, array($this, 'isPackageAcceptable')) as $candidate) { - $candidates[] = $candidate; - if ($candidate->id < 1) { - $candidate->setId($this->id++); - $this->packages[$this->id - 2] = $candidate; - } - } - } - if ($mustMatchName) { - $candidates = array_filter($candidates, function ($candidate) use ($name) { - return $candidate->getName() == $name; - }); if (isset($this->packageByExactName[$name])) { - $candidates = array_merge($candidates, $this->packageByExactName[$name]); + $candidates = $this->packageByExactName[$name]; } } elseif (isset($this->packageByName[$name])) { - $candidates = array_merge($candidates, $this->packageByName[$name]); + $candidates = $this->packageByName[$name]; } $matches = $provideMatches = array(); @@ -287,23 +217,6 @@ class Pool implements \Countable return $prefix.' '.$package->getPrettyString(); } - public function isPackageAcceptable($name, $stability) - { - foreach ((array) $name as $n) { - // allow if package matches the global stability requirement and has no exception - if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) { - return true; - } - - // allow if package matches the package-specific stability flag - if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) { - return true; - } - } - - return false; - } - /** * Checks if the package matches the given constraint directly or through * provided or replaced packages diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php new file mode 100644 index 000000000..2ec6dd680 --- /dev/null +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -0,0 +1,147 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\DependencyResolver; + +use Composer\Package\AliasPackage; +use Composer\Package\BasePackage; +use Composer\Package\PackageInterface; +use Composer\Repository\AsyncRepositoryInterface; +use Composer\Repository\InstalledRepositoryInterface; +use Composer\Repository\LockArrayRepository; +use Composer\Repository\PlatformRepository; + +/** + * @author Nils Adermann + */ +class PoolBuilder +{ + private $isPackageAcceptableCallable; + private $filterRequires; + private $rootAliases; + + private $loadedNames = array(); + + private $id = 1; + private $packages = array(); + private $priorities = array(); + + public function __construct($isPackageAcceptableCallable, array $filterRequires = array()) + { + $this->isPackageAcceptableCallable = $isPackageAcceptableCallable; + $this->filterRequires = $filterRequires; + } + + public function buildPool(array $repositories, array $rootAliases, Request $request) + { + $this->pool = new Pool($this->filterRequires); + $this->rootAliases = $rootAliases; + + // TODO do we really want the request here? kind of want a root requirements thingy instead + $loadNames = array(); + foreach ($request->getJobs() as $job) { + switch ($job['cmd']) { + case 'install': + $loadNames[$job['packageName']] = true; + break; + } + } + + foreach ($repositories as $repository) { + if ($repository instanceof ComposerRepository && $repository->hasProviders()) { + $this->providerRepos[] = $repository; + $repository->setRootAliases($this->rootAliases); + $repository->resetPackageIds(); + } + } + + while (!empty($loadNames)) { + $loadIds = array(); + foreach ($repositories as $key => $repository) { + if ($repository instanceof AsyncRepositoryInterface) { + $loadIds[$key] = $repository->requestPackages($loadNames); + } + } + + foreach ($loadNames as $name => $void) { + $this->loadedNames[$name] = true; + } + + $newLoadNames = array(); + foreach ($repositories as $key => $repository) { + if ($repository instanceof PlatformRepository || $repository instanceof InstalledRepositoryInterface) { + continue; + } + + if ($repository instanceof AsyncRepositoryInterface) { + $packages = $repository->returnPackages($loadIds[$key]); + } else { + $packages = $repository->loadPackages($loadNames); + } + + foreach ($packages as $package) { + if (call_user_func($this->isPackageAcceptableCallable, $package->getNames(), $package->getStability())) { + $newLoadNames += $this->loadPackage($package, $key); + } + } + } + + $loadNames = $newLoadNames; + } + + foreach ($repositories as $key => $repository) { + if ($repository instanceof PlatformRepository || + $repository instanceof InstalledRepositoryInterface) { + foreach ($repository->getPackages() as $package) { + $this->loadPackage($package, $key); + } + } + } + + $this->pool->setPackages($this->packages, $this->priorities); + + return $this->pool; + } + + private function loadPackage(PackageInterface $package, $repoIndex) + { + $package->setId($this->id++); + $this->packages[] = $package; + $this->priorities[$this->id - 2] = -$repoIndex; + + // handle root package aliases + $name = $package->getName(); + if (isset($this->rootAliases[$name][$package->getVersion()])) { + $alias = $this->rootAliases[$name][$package->getVersion()]; + if ($package instanceof AliasPackage) { + $package = $package->getAliasOf(); + } + $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']); + $aliasPackage->setRootPackageAlias(true); + $aliasPackage->setId($this->id++); + + $package->getRepository()->addPackage($aliasPackage); // TODO do we need this? + $this->packages[] = $aliasPackage; + } + + $loadNames = array(); + foreach ($package->getRequires() as $link) { + $require = $link->getTarget(); + if (!isset($this->loadedNames[$require])) { + $loadNames[$require] = true; + } + } + + return $loadNames; + } +} + diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index de24b0991..7cd3a9813 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -71,7 +71,7 @@ class Problem * @param array $installedMap A map of all installed packages * @return string */ - public function getPrettyString(array $installedMap = array()) + public function getPrettyString(array $installedMap = array(), array $learnedPool = array()) { $reasons = call_user_func_array('array_merge', array_reverse($this->reasons)); @@ -168,7 +168,7 @@ class Problem $messages[] = $this->jobToText($job); } elseif ($rule) { if ($rule instanceof Rule) { - $messages[] = $rule->getPrettyString($this->pool, $installedMap); + $messages[] = $rule->getPrettyString($this->pool, $installedMap, $learnedPool); } } } diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 1fe8cbd30..a627de61c 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -126,7 +126,7 @@ abstract class Rule abstract public function isAssertion(); - public function getPrettyString(Pool $pool, array $installedMap = array()) + public function getPrettyString(Pool $pool, array $installedMap = array(), array $learnedPool = array()) { $literals = $this->getLiterals(); @@ -230,7 +230,18 @@ abstract class Rule case self::RULE_PACKAGE_IMPLICIT_OBSOLETES: return $ruleText; case self::RULE_LEARNED: - return 'Conclusion: '.$ruleText; + // TODO not sure this is a good idea, most of these rules should be listed in the problem anyway + $learnedString = '(learned rule, '; + if (isset($learnedPool[$this->reasonData])) { + foreach ($learnedPool[$this->reasonData] as $learnedRule) { + $learnedString .= $learnedRule->getPrettyString($pool, $installedMap, $learnedPool); + } + } else { + $learnedString .= 'reasoning unavailable'; + } + $learnedString .= ')'; + + return 'Conclusion: '.$ruleText.' '.$learnedString; case self::RULE_PACKAGE_ALIAS: return $ruleText; default: diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 959f1dc4c..aa5432188 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -244,7 +244,7 @@ class Solver } if ($this->problems) { - throw new SolverProblemsException($this->problems, $this->installedMap); + throw new SolverProblemsException($this->problems, $this->installedMap, $this->learnedPool); } $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions); diff --git a/src/Composer/DependencyResolver/SolverProblemsException.php b/src/Composer/DependencyResolver/SolverProblemsException.php index 142895697..0184bba9c 100644 --- a/src/Composer/DependencyResolver/SolverProblemsException.php +++ b/src/Composer/DependencyResolver/SolverProblemsException.php @@ -21,11 +21,13 @@ class SolverProblemsException extends \RuntimeException { protected $problems; protected $installedMap; + protected $learnedPool; - public function __construct(array $problems, array $installedMap) + public function __construct(array $problems, array $installedMap, array $learnedPool) { $this->problems = $problems; $this->installedMap = $installedMap; + $this->learnedPool = $learnedPool; parent::__construct($this->createMessage(), 2); } @@ -35,7 +37,7 @@ class SolverProblemsException extends \RuntimeException $text = "\n"; $hasExtensionProblems = false; foreach ($this->problems as $i => $problem) { - $text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n"; + $text .= " Problem ".($i + 1).$problem->getPrettyString($this->installedMap, $this->learnedPool)."\n"; if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) { $hasExtensionProblems = true; diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 8f6427a9a..95d5b6605 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -467,7 +467,7 @@ class Installer $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $repositorySet, $installedRepo, $request); - $pool = $repositorySet->createPool(); + $pool = $repositorySet->createPool($request); // force dev packages to have the latest links if we update or install from a (potentially new) lock $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links'); @@ -701,7 +701,7 @@ class Installer // solve deps to see which get removed $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $repositorySet, $installedRepo, $request); - $solver = new Solver($policy, $repositorySet->createPool(), $installedRepo, $this->io); + $solver = new Solver($policy, $repositorySet->createPool($request), $installedRepo, $this->io); $ops = $solver->solve($request, $this->ignorePlatformReqs); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $repositorySet, $installedRepo, $request, $ops); diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 57ec74233..405d43261 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -14,9 +14,9 @@ namespace Composer\Package; use Composer\Json\JsonFile; use Composer\Installer\InstallationManager; +use Composer\Repository\LockArrayRepository; use Composer\Repository\RepositoryManager; use Composer\Util\ProcessExecutor; -use Composer\Repository\ArrayRepository; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Loader\ArrayLoader; use Composer\Util\Git as GitUtil; @@ -150,7 +150,7 @@ class Locker public function getLockedRepository($withDevReqs = false) { $lockData = $this->getLockData(); - $packages = new ArrayRepository(); + $packages = new LockArrayRepository(); $lockedPackages = $lockData['packages']; if ($withDevReqs) { diff --git a/src/Composer/Repository/AsyncRepositoryInterface.php b/src/Composer/Repository/AsyncRepositoryInterface.php new file mode 100644 index 000000000..91f543dbf --- /dev/null +++ b/src/Composer/Repository/AsyncRepositoryInterface.php @@ -0,0 +1,38 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\Package\PackageInterface; + +/** + * Repository interface. + * + * @author Nils Adermann + * @author Konstantin Kudryashov + * @author Jordi Boggiano + */ +interface AsyncRepositoryInterface +{ + /** + * @param array $names Names of packages to retrieve data for + * @return scalar Id to be passed to later loadPackages call + */ + public function requestPackages(array $names); + + /** + * @param array $names + * @return scalar id for load call + */ + public function returnPackages($loadId); +} + diff --git a/src/Composer/Repository/BaseRepository.php b/src/Composer/Repository/BaseRepository.php index 2b30b63cd..e9e97bb91 100644 --- a/src/Composer/Repository/BaseRepository.php +++ b/src/Composer/Repository/BaseRepository.php @@ -24,6 +24,21 @@ use Composer\Package\Link; */ abstract class BaseRepository implements RepositoryInterface { + // TODO should this stay here? some repos need a better implementation + public function loadPackages(array $packageNameMap) + { + $packages = $this->getPackages(); + + $result = array(); + foreach ($packages as $package) { + if (isset($packageNameMap[$package->getName()])) { + $result[] = $package; + } + } + + return $result; + } + /** * Returns a list of links causing the requested needle packages to be installed, as an associative array with the * dependent's name as key, and an array containing in order the PackageInterface and Link describing the relationship diff --git a/src/Composer/Repository/LockArrayRepository.php b/src/Composer/Repository/LockArrayRepository.php new file mode 100644 index 000000000..0ccc998d3 --- /dev/null +++ b/src/Composer/Repository/LockArrayRepository.php @@ -0,0 +1,25 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +/** + * Lock array repository. + * + * Regular array repository, only uses a different type to identify the lock file as the source of info + * + * @author Nils Adermann + */ +class LockArrayRepository extends ArrayRepository implements RepositoryInterface +{ +} + diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index 9a2aaf3b5..703f92e35 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -55,6 +55,7 @@ interface RepositoryInterface extends \Countable */ public function findPackages($name, $constraint = null); + // TODO this should really not be in this generic interface anymore /** * Returns list of registered packages. * @@ -62,6 +63,14 @@ interface RepositoryInterface extends \Countable */ public function getPackages(); + /** + * Returns list of registered packages with the supplied name + * + * @param bool[] $packageNameMap + * @return PackageInterface[] + */ + public function loadPackages(array $packageNameMap); + /** * Searches the repository for packages containing the query * diff --git a/src/Composer/Repository/RepositorySet.php b/src/Composer/Repository/RepositorySet.php index 4bea054f9..bac63dd36 100644 --- a/src/Composer/Repository/RepositorySet.php +++ b/src/Composer/Repository/RepositorySet.php @@ -13,6 +13,8 @@ namespace Composer\Repository; use Composer\DependencyResolver\Pool; +use Composer\DependencyResolver\PoolBuilder; +use Composer\DependencyResolver\Request; use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Repository\CompositeRepository; @@ -31,9 +33,6 @@ class RepositorySet /** @var RepositoryInterface[] */ private $repositories = array(); - /** @var ComposerRepository[] */ - private $providerRepos = array(); - private $acceptableStabilities; private $stabilityFlags; protected $filterRequires; @@ -79,9 +78,6 @@ class RepositorySet foreach ($repos as $repo) { $this->repositories[] = $repo; - if ($repo instanceof ComposerRepository && $repo->hasProviders()) { - $this->providerRepos[] = $repo; - } } } @@ -133,20 +129,43 @@ class RepositorySet return $candidates; } + public function getPriority(RepositoryInterface $repo) + { + $priority = array_search($repo, $this->repositories, true); + + if (false === $priority) { + throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool."); + } + + return -$priority; + } + /** * Create a pool for dependency resolution from the packages in this repository set. * * @return Pool */ - public function createPool() + public function createPool(Request $request) { - $this->pool = new Pool($this->acceptableStabilities, $this->stabilityFlags, $this->filterRequires); + $poolBuilder = new PoolBuilder(array($this, 'isPackageAcceptable'), $this->filterRequires); - foreach ($this->repositories as $repository) { - $this->pool->addRepository($repository, $this->rootAliases); + return $this->pool = $poolBuilder->buildPool($this->repositories, $this->rootAliases, $request); + } + + // TODO unify this with above in some simpler version without "request"? + public function createPoolForPackage($packageName) + { + return $this->createPoolForPackages(array($packageName)); + } + + public function createPoolForPackages($packageNames) + { + $request = new Request(); + foreach ($packageNames as $packageName) { + $request->install($packageName); } - return $this->pool; + return $this->createPool($request); } /** diff --git a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php index dedb452e2..c1637b8e4 100644 --- a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php +++ b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php @@ -21,6 +21,7 @@ use Composer\Package\AliasPackage; use Composer\Repository\RepositorySet; use Composer\Semver\Constraint\Constraint; use Composer\TestCase; +use http\Env\Request; class DefaultPolicyTest extends TestCase { @@ -47,7 +48,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA = $this->getPackage('A', '1.0')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA->getId()); $expected = array($packageA->getId()); @@ -63,7 +64,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA2 = $this->getPackage('A', '2.0')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA1->getId(), $packageA2->getId()); $expected = array($packageA2->getId()); @@ -79,7 +80,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA2 = $this->getPackage('A', '1.0.1-alpha')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA1->getId(), $packageA2->getId()); $expected = array($packageA2->getId()); @@ -95,7 +96,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA2 = $this->getPackage('A', '1.0.1-alpha')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA1->getId(), $packageA2->getId()); $expected = array($packageA1->getId()); @@ -112,7 +113,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA2 = $this->getPackage('A', '1.0.0')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA1->getId(), $packageA2->getId()); $expected = array($packageA2->getId()); @@ -129,7 +130,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($this->repoInstalled); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA->getId(), $packageAInstalled->getId()); $expected = array($packageA->getId()); @@ -150,7 +151,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($otherRepository); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA->getId(), $packageAImportant->getId()); $expected = array($packageAImportant->getId()); @@ -173,7 +174,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($repo1); $this->repositorySet->addRepository($repo2); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($package1->getId(), $package2->getId(), $package3->getId(), $package4->getId()); $expected = array($package2->getId()); @@ -185,7 +186,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($repo2); $this->repositorySet->addRepository($repo1); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $expected = array($package4->getId()); $selected = $this->policy->selectPreferredPackages($pool, array(), $literals); @@ -209,7 +210,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($repoImportant); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $packages = $pool->whatProvides('a', new Constraint('=', '2.1.9999999.9999999-dev')); $literals = array(); @@ -234,7 +235,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackages(array('A', 'B')); $literals = array($packageA->getId(), $packageB->getId()); $expected = $literals; @@ -253,7 +254,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackages(array('A', 'B')); $literals = array($packageA->getId(), $packageB->getId()); $expected = $literals; @@ -274,7 +275,7 @@ class DefaultPolicyTest extends TestCase $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackages(array('vendor-a/replacer', 'vendor-b/replacer')); $literals = array($packageA->getId(), $packageB->getId()); $expected = $literals; @@ -290,7 +291,7 @@ class DefaultPolicyTest extends TestCase $repositorySet = new RepositorySet(array(), 'dev'); $repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackages(array('vendor-a/replacer', 'vendor-b/replacer')); $literals = array($packageA->getId(), $packageB->getId()); $expected = $literals; @@ -317,7 +318,7 @@ class DefaultPolicyTest extends TestCase $this->repo->addPackage($packageA2 = $this->getPackage('A', '2.0')); $this->repositorySet->addRepository($this->repo); - $pool = $this->repositorySet->createPool(); + $pool = $this->repositorySet->createPoolForPackage('A'); $literals = array($packageA1->getId(), $packageA2->getId()); $expected = array($packageA1->getId()); diff --git a/tests/Composer/Test/DependencyResolver/PoolTest.php b/tests/Composer/Test/DependencyResolver/PoolTest.php index 5169586f6..74767c525 100644 --- a/tests/Composer/Test/DependencyResolver/PoolTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolTest.php @@ -22,90 +22,25 @@ class PoolTest extends TestCase public function testPool() { $pool = $this->createPool(); - $repo = new ArrayRepository; $package = $this->getPackage('foo', '1'); - $repo->addPackage($package); - $pool->addRepository($repo); + $pool->setPackages(array($package)); $this->assertEquals(array($package), $pool->whatProvides('foo')); $this->assertEquals(array($package), $pool->whatProvides('foo')); } - public function testPoolIgnoresIrrelevantPackages() - { - $pool = new Pool(array('stable' => BasePackage::STABILITY_STABLE), array('bar' => BasePackage::STABILITY_BETA)); - $repo = new ArrayRepository; - $repo->addPackage($package = $this->getPackage('bar', '1')); - $repo->addPackage($betaPackage = $this->getPackage('bar', '1-beta')); - $repo->addPackage($alphaPackage = $this->getPackage('bar', '1-alpha')); - $repo->addPackage($package2 = $this->getPackage('foo', '1')); - $repo->addPackage($rcPackage2 = $this->getPackage('foo', '1rc')); - - $pool->addRepository($repo); - - $this->assertEquals(array($package, $betaPackage), $pool->whatProvides('bar')); - $this->assertEquals(array($package2), $pool->whatProvides('foo')); - } - - /** - * @expectedException \RuntimeException - */ - public function testGetPriorityForNotRegisteredRepository() - { - $pool = $this->createPool(); - $repository = new ArrayRepository; - - $pool->getPriority($repository); - } - - public function testGetPriorityWhenRepositoryIsRegistered() - { - $pool = $this->createPool(); - $firstRepository = new ArrayRepository; - $pool->addRepository($firstRepository); - $secondRepository = new ArrayRepository; - $pool->addRepository($secondRepository); - - $firstPriority = $pool->getPriority($firstRepository); - $secondPriority = $pool->getPriority($secondRepository); - - $this->assertEquals(0, $firstPriority); - $this->assertEquals(-1, $secondPriority); - } - - public function testWhatProvidesSamePackageForDifferentRepositories() - { - $pool = $this->createPool(); - $firstRepository = new ArrayRepository; - $secondRepository = new ArrayRepository; - - $firstPackage = $this->getPackage('foo', '1'); - $secondPackage = $this->getPackage('foo', '1'); - $thirdPackage = $this->getPackage('foo', '2'); - - $firstRepository->addPackage($firstPackage); - $secondRepository->addPackage($secondPackage); - $secondRepository->addPackage($thirdPackage); - - $pool->addRepository($firstRepository); - $pool->addRepository($secondRepository); - - $this->assertEquals(array($firstPackage, $secondPackage, $thirdPackage), $pool->whatProvides('foo')); - } - public function testWhatProvidesPackageWithConstraint() { $pool = $this->createPool(); - $repository = new ArrayRepository; $firstPackage = $this->getPackage('foo', '1'); $secondPackage = $this->getPackage('foo', '2'); - $repository->addPackage($firstPackage); - $repository->addPackage($secondPackage); - - $pool->addRepository($repository); + $pool->setPackages(array( + $firstPackage, + $secondPackage, + )); $this->assertEquals(array($firstPackage, $secondPackage), $pool->whatProvides('foo')); $this->assertEquals(array($secondPackage), $pool->whatProvides('foo', $this->getVersionConstraint('==', '2'))); @@ -114,11 +49,9 @@ class PoolTest extends TestCase public function testPackageById() { $pool = $this->createPool(); - $repository = new ArrayRepository; $package = $this->getPackage('foo', '1'); - $repository->addPackage($package); - $pool->addRepository($repository); + $pool->setPackages(array($package)); $this->assertSame($package, $pool->packageById(1)); } diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index e9753c848..9acd45455 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -22,13 +22,6 @@ use Composer\TestCase; class RuleSetTest extends TestCase { - protected $pool; - - public function setUp() - { - $this->pool = new Pool(array('stable' => BasePackage::STABILITY_STABLE)); - } - public function testAdd() { $rules = array( @@ -146,9 +139,11 @@ class RuleSetTest extends TestCase public function testPrettyString() { - $repo = new ArrayRepository; - $repo->addPackage($p = $this->getPackage('foo', '2.1')); - $this->pool->addRepository($repo); + $pool = new Pool(array('stable' => BasePackage::STABILITY_STABLE)); + $pool->setPackages(array( + $p = $this->getPackage('foo', '2.1'), + )); + $p->setId(1); $ruleSet = new RuleSet; $literal = $p->getId(); @@ -156,7 +151,7 @@ class RuleSetTest extends TestCase $ruleSet->add($rule, RuleSet::TYPE_JOB); - $this->assertContains('JOB : Install command rule (install foo 2.1)', $ruleSet->getPrettyString($this->pool)); + $this->assertContains('JOB : Install command rule (install foo 2.1)', $ruleSet->getPrettyString($pool)); } private function getRuleMock() diff --git a/tests/Composer/Test/DependencyResolver/RuleTest.php b/tests/Composer/Test/DependencyResolver/RuleTest.php index c9b3dbe1a..cb83266c8 100644 --- a/tests/Composer/Test/DependencyResolver/RuleTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleTest.php @@ -22,13 +22,6 @@ use Composer\TestCase; class RuleTest extends TestCase { - protected $pool; - - public function setUp() - { - $this->pool = new Pool(array('stable' => BasePackage::STABILITY_STABLE)); - } - public function testGetHash() { $rule = new GenericRule(array(123), Rule::RULE_JOB_INSTALL, null); @@ -100,13 +93,16 @@ class RuleTest extends TestCase public function testPrettyString() { - $repo = new ArrayRepository; - $repo->addPackage($p1 = $this->getPackage('foo', '2.1')); - $repo->addPackage($p2 = $this->getPackage('baz', '1.1')); - $this->pool->addRepository($repo); + $pool = new Pool(array('stable' => BasePackage::STABILITY_STABLE)); + $pool->setPackages(array( + $p1 = $this->getPackage('foo', '2.1'), + $p2 = $this->getPackage('baz', '1.1'), + )); + $p1->setId(1); + $p2->setId(2); $rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_JOB_INSTALL, null); - $this->assertEquals('Install command rule (don\'t install baz 1.1|install foo 2.1)', $rule->getPrettyString($this->pool)); + $this->assertEquals('Install command rule (don\'t install baz 1.1|install foo 2.1)', $rule->getPrettyString($pool)); } } diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index e4b02968f..0d221a8ab 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -20,6 +20,7 @@ use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Solver; use Composer\DependencyResolver\SolverProblemsException; use Composer\Package\Link; +use Composer\Repository\InstalledArrayRepository; use Composer\Repository\RepositorySet; use Composer\TestCase; use Composer\Semver\Constraint\MultiConstraint; @@ -31,12 +32,13 @@ class SolverTest extends TestCase protected $repoInstalled; protected $request; protected $policy; + protected $solver; public function setUp() { $this->repoSet = new RepositorySet(array()); $this->repo = new ArrayRepository; - $this->repoInstalled = new ArrayRepository; + $this->repoInstalled = new InstalledArrayRepository; $this->request = new Request($this->repoSet); $this->policy = new DefaultPolicy; @@ -71,6 +73,7 @@ class SolverTest extends TestCase $this->request->install('B', $this->getVersionConstraint('==', '1')); + $this->createSolver(); try { $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not result in exception.'); @@ -94,8 +97,6 @@ class SolverTest extends TestCase $this->repoSet->addRepository($repo1); $this->repoSet->addRepository($repo2); - $this->solver = new Solver($this->policy, $this->repoSet->createPool(), $this->repoInstalled, new NullIO()); - $this->request->install('foo'); $this->checkSolverResult(array( @@ -447,6 +448,7 @@ class SolverTest extends TestCase // must explicitly pick the provider, so error in this case $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException'); + $this->createSolver(); $this->solver->solve($this->request); } @@ -480,6 +482,7 @@ class SolverTest extends TestCase $this->request->install('A'); $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException'); + $this->createSolver(); $this->solver->solve($this->request); } @@ -652,6 +655,7 @@ class SolverTest extends TestCase $this->setExpectedException('Composer\DependencyResolver\SolverProblemsException'); + $this->createSolver(); $this->solver->solve($this->request); } @@ -668,6 +672,7 @@ class SolverTest extends TestCase $this->request->install('A'); $this->request->install('B'); + $this->createSolver(); try { $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not result in exception.'); @@ -697,6 +702,7 @@ class SolverTest extends TestCase $this->request->install('A'); + $this->createSolver(); try { $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not result in exception.'); @@ -744,6 +750,7 @@ class SolverTest extends TestCase $this->request->install('A'); + $this->createSolver(); try { $transaction = $this->solver->solve($this->request); $this->fail('Unsolvable conflict did not result in exception.'); @@ -843,12 +850,16 @@ class SolverTest extends TestCase { $this->repoSet->addRepository($this->repoInstalled); $this->repoSet->addRepository($this->repo); + } - $this->solver = new Solver($this->policy, $this->repoSet->createPool(), $this->repoInstalled, new NullIO()); + protected function createSolver() + { + $this->solver = new Solver($this->policy, $this->repoSet->createPool($this->request), $this->repoInstalled, new NullIO()); } protected function checkSolverResult(array $expected) { + $this->createSolver(); $transaction = $this->solver->solve($this->request); $result = array(); diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 8614495ee..562a71518 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -30,7 +30,6 @@ use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatter; use Composer\TestCase; -use Composer\IO\BufferIO; class InstallerTest extends TestCase {