1
0
Fork 0

Revert "Merge remote-tracking branch 'naderman/load-no-providers'"

This reverts commit 3e85f82373, reversing
changes made to b025d0982b.
pull/4146/merge
Nils Adermann 2015-06-18 15:40:27 +02:00
parent 74e7c5fe22
commit 75c501251d
5 changed files with 156 additions and 193 deletions

View File

@ -276,7 +276,6 @@ EOT
$pool = new Pool($stability); $pool = new Pool($stability);
$pool->addRepository($sourceRepo); $pool->addRepository($sourceRepo);
$pool->loadRecursively(array($name));
// find the latest version if there are multiple // find the latest version if there are multiple
$versionSelector = new VersionSelector($pool); $versionSelector = new VersionSelector($pool);

View File

@ -99,97 +99,12 @@ class Pool
if ($repo instanceof ComposerRepository && $repo->hasProviders()) { if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
$this->providerRepos[] = $repo; $this->providerRepos[] = $repo;
$repo->setRootAliases($rootAliases); $repo->setRootAliases($rootAliases);
$repo->resetPackageIds();
} else { } else {
foreach ($repo->getPackages() as $package) { foreach ($repo->getPackages() as $package) {
$this->loadPackage($package, $rootAliases, $exempt);
}
}
}
}
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;
}
/**
* Retrieves the package object for a given package id.
*
* @param int $id
* @return PackageInterface
*/
public function packageById($id)
{
return $this->packages[$id - 1];
}
/**
* Ensures that all given names and their requirements are loaded.
*
* @param array $packageNames A list of names that need to be available
*/
public function loadRecursively(array $packageNames)
{
$loadedMap = array();
do {
$newPackageNames = array();
$loadedCount = count($loadedMap);
foreach ($this->providerRepos as $repo) {
$packages = $repo->loadRecursively(
$packageNames,
array($this, 'isPackageAcceptable')
);
foreach ($packages as $package) {
$name = $package->getName();
if (!isset($loadedMap[$name])) {
$loadedMap[$name] = true;
$newPackageNames[] = $name;
}
$this->loadPackage($package, $repo->getRootAliases());
}
}
$packageNames = $newPackageNames;
} while (count($loadedMap) > $loadedCount);
}
/**
* Searches all packages providing the given package name and match the constraint
*
* @param string $name The package name to be searched for
* @param LinkConstraintInterface $constraint A constraint that all returned
* packages must match or null to return all
* @param bool $mustMatchName Whether the name of returned packages
* must match the given name
* @return PackageInterface[] A set of packages
*/
public function whatProvides($name, LinkConstraintInterface $constraint = null, $mustMatchName = false)
{
$key = ((int) $mustMatchName).$constraint;
if (isset($this->providerCache[$name][$key])) {
return $this->providerCache[$name][$key];
}
return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName);
}
private function loadPackage(PackageInterface $package, array $rootAliases, $acceptableExemption = false)
{
$names = $package->getNames(); $names = $package->getNames();
$stability = $package->getStability(); $stability = $package->getStability();
if ($exempt || $this->isPackageAcceptable($names, $stability)) {
if (!$acceptableExemption && !$this->isPackageAcceptable($names, $stability)) {
return;
}
$package->setId($this->id++); $package->setId($this->id++);
$this->packages[] = $package; $this->packages[] = $package;
$this->packageByExactName[$package->getName()][$package->id] = $package; $this->packageByExactName[$package->getName()][$package->id] = $package;
@ -218,6 +133,52 @@ class Pool
} }
} }
} }
}
}
}
}
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;
}
/**
* Retrieves the package object for a given package id.
*
* @param int $id
* @return PackageInterface
*/
public function packageById($id)
{
return $this->packages[$id - 1];
}
/**
* Searches all packages providing the given package name and match the constraint
*
* @param string $name The package name to be searched for
* @param LinkConstraintInterface $constraint A constraint that all returned
* packages must match or null to return all
* @param bool $mustMatchName Whether the name of returned packages
* must match the given name
* @return PackageInterface[] A set of packages
*/
public function whatProvides($name, LinkConstraintInterface $constraint = null, $mustMatchName = false)
{
$key = ((int) $mustMatchName).$constraint;
if (isset($this->providerCache[$name][$key])) {
return $this->providerCache[$name][$key];
}
return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName);
}
/** /**
* @see whatProvides * @see whatProvides
@ -226,12 +187,25 @@ class Pool
{ {
$candidates = array(); $candidates = array();
foreach ($this->providerRepos as $repo) {
foreach ($repo->whatProvides($this, $name) as $candidate) {
$candidates[] = $candidate;
if ($candidate->id < 1) {
$candidate->setId($this->id++);
$this->packages[$this->id - 2] = $candidate;
}
}
}
if ($mustMatchName) { if ($mustMatchName) {
$candidates = array_filter($candidates, function ($candidate) use ($name) {
return $candidate->getName() == $name;
});
if (isset($this->packageByExactName[$name])) { if (isset($this->packageByExactName[$name])) {
$candidates = $this->packageByExactName[$name]; $candidates = array_merge($candidates, $this->packageByExactName[$name]);
} }
} elseif (isset($this->packageByName[$name])) { } elseif (isset($this->packageByName[$name])) {
$candidates = $this->packageByName[$name]; $candidates = array_merge($candidates, $this->packageByName[$name]);
} }
$matches = $provideMatches = array(); $matches = $provideMatches = array();

View File

@ -169,18 +169,6 @@ class Solver
$this->jobs = $request->getJobs(); $this->jobs = $request->getJobs();
$this->setupInstalledMap(); $this->setupInstalledMap();
$packageNames = array();
foreach ($this->jobs as $job) {
switch ($job['cmd']) {
case 'install':
$packageNames[$job['packageName']] = true;
break;
}
}
$this->pool->loadRecursively(array_keys($packageNames));
$this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs); $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
$this->checkForRootRequireProblems($ignorePlatformReqs); $this->checkForRootRequireProblems($ignorePlatformReqs);
$this->decisions = new Decisions($this->pool); $this->decisions = new Decisions($this->pool);

View File

@ -43,9 +43,10 @@ class ComposerRepository extends ArrayRepository
protected $searchUrl; protected $searchUrl;
protected $hasProviders = false; protected $hasProviders = false;
protected $providersUrl; protected $providersUrl;
protected $loadedMap = array();
protected $lazyProvidersUrl; protected $lazyProvidersUrl;
protected $providerListing; protected $providerListing;
protected $providers = array();
protected $providersByUid = array();
protected $loader; protected $loader;
protected $rootAliases; protected $rootAliases;
protected $allowSslDowngrade = false; protected $allowSslDowngrade = false;
@ -95,51 +96,6 @@ class ComposerRepository extends ArrayRepository
$this->rootAliases = $rootAliases; $this->rootAliases = $rootAliases;
} }
public function getRootAliases()
{
return $this->rootAliases;
}
/**
* Load all packages with given names and dependencies
*
* @param array $packageNames
* @param callable|null $acceptableCallback Callback to filter packages
*
* @return array The loaded package objects
*/
public function loadRecursively(array $packageNames, $acceptableCallback)
{
$workQueue = new \SplQueue;
foreach ($packageNames as $packageName) {
$workQueue->enqueue($packageName);
}
$loadedPackages = array();
while (!$workQueue->isEmpty()) {
$packageName = $workQueue->dequeue();
if (isset($this->loadedMap[$packageName])) {
continue;
}
$this->loadedMap[$packageName] = true;
$packages = $this->loadName($packageName, $acceptableCallback);
foreach ($packages as $package) {
$loadedPackages[] = $package;
$requires = $package->getRequires();
foreach ($requires as $link) {
$workQueue->enqueue($link->getTarget());
}
}
}
return $loadedPackages;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -155,7 +111,7 @@ class ComposerRepository extends ArrayRepository
foreach ($this->getProviderNames() as $providerName) { foreach ($this->getProviderNames() as $providerName) {
if ($name === $providerName) { if ($name === $providerName) {
$packages = $this->loadName($providerName, null, false); $packages = $this->whatProvides(new Pool('dev'), $providerName);
foreach ($packages as $package) { foreach ($packages as $package) {
if ($name == $package->getName() && $version === $package->getVersion()) { if ($name == $package->getName() && $version === $package->getVersion()) {
return $package; return $package;
@ -186,7 +142,7 @@ class ComposerRepository extends ArrayRepository
foreach ($this->getProviderNames() as $providerName) { foreach ($this->getProviderNames() as $providerName) {
if ($name === $providerName) { if ($name === $providerName) {
$packages = $this->loadName($providerName, null, false); $packages = $this->whatProvides(new Pool('dev'), $providerName);
foreach ($packages as $package) { foreach ($packages as $package) {
if ($name == $package->getName() && (null === $version || $version === $package->getVersion())) { if ($name == $package->getName() && (null === $version || $version === $package->getVersion())) {
$packages[] = $package; $packages[] = $package;
@ -284,17 +240,22 @@ class ComposerRepository extends ArrayRepository
return $this->hasProviders; return $this->hasProviders;
} }
/** public function resetPackageIds()
* Loads package data for a given package name or provider name
*
* @param string $name
* @param callable|null $acceptableCallback A callback to check if a package should be loaded
* @param bool $exactMatch Whether packages only providing the name should be ignored
*
* @return array All packages that were loaded
*/
protected function loadName($name, $acceptableCallback, $exactMatch = true)
{ {
foreach ($this->providersByUid as $package) {
if ($package instanceof AliasPackage) {
$package->getAliasOf()->setId(-1);
}
$package->setId(-1);
}
}
public function whatProvides(Pool $pool, $name)
{
if (isset($this->providers[$name])) {
return $this->providers[$name];
}
// skip platform packages // skip platform packages
if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) { if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) {
return array(); return array();
@ -335,32 +296,69 @@ class ComposerRepository extends ArrayRepository
$packages = $this->fetchFile($url, $cacheKey, $hash); $packages = $this->fetchFile($url, $cacheKey, $hash);
} }
$loadedPackages = array(); $this->providers[$name] = array();
foreach ($packages['packages'] as $packageName => $versions) { foreach ($packages['packages'] as $versions) {
if ($exactMatch && $packageName !== $name) {
continue;
}
foreach ($versions as $version) { foreach ($versions as $version) {
if ($acceptableCallback && !call_user_func( // avoid loading the same objects twice
$acceptableCallback, strtolower($version['name']), VersionParser::parseStability($version['version']) if (isset($this->providersByUid[$version['uid']])) {
)) { // skip if already assigned
if (!isset($this->providers[$name][$version['uid']])) {
// expand alias in two packages
if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
$this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
$this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
} else {
$this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
}
// check for root aliases
if (isset($this->providersByUid[$version['uid'].'-root'])) {
$this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
}
}
} else {
if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
continue; continue;
} }
// load acceptable packages in the providers // load acceptable packages in the providers
$package = $this->createPackage($version, 'Composer\Package\Package'); $package = $this->createPackage($version, 'Composer\Package\Package');
$this->addPackage($package); $package->setRepository($this);
$loadedPackages[] = $package;
if ($package instanceof AliasPackage) { if ($package instanceof AliasPackage) {
$loadedPackages[] = $package->getAliasOf(); $aliased = $package->getAliasOf();
$aliased->setRepository($this);
$this->providers[$name][$version['uid']] = $aliased;
$this->providers[$name][$version['uid'].'-alias'] = $package;
// override provider with its alias so it can be expanded in the if block above
$this->providersByUid[$version['uid']] = $package;
} else {
$this->providers[$name][$version['uid']] = $package;
$this->providersByUid[$version['uid']] = $package;
}
// handle root package aliases
unset($rootAliasData);
if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
$rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
} elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
$rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
}
if (isset($rootAliasData)) {
$alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
$alias->setRepository($this);
$this->providers[$name][$version['uid'].'-root'] = $alias;
$this->providersByUid[$version['uid'].'-root'] = $alias;
}
} }
} }
} }
return $loadedPackages; return $this->providers[$name];
} }
/** /**

View File

@ -96,7 +96,7 @@ class ComposerRepositoryTest extends TestCase
); );
} }
public function testLoadRecursively() public function testWhatProvides()
{ {
$repo = $this->getMockBuilder('Composer\Repository\ComposerRepository') $repo = $this->getMockBuilder('Composer\Repository\ComposerRepository')
->disableOriginalConstructor() ->disableOriginalConstructor()
@ -124,41 +124,45 @@ class ComposerRepositoryTest extends TestCase
->method('fetchFile') ->method('fetchFile')
->will($this->returnValue(array( ->will($this->returnValue(array(
'packages' => array( 'packages' => array(
'a' => array( array(array(
'dev-master' => array(
'uid' => 1, 'uid' => 1,
'name' => 'a', 'name' => 'a',
'version' => 'dev-master', 'version' => 'dev-master',
'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')), 'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
), )),
'dev-develop' => array( array(array(
'uid' => 2, 'uid' => 2,
'name' => 'a', 'name' => 'a',
'version' => 'dev-develop', 'version' => 'dev-develop',
'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')), 'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')),
), )),
'0.6' => array( array(array(
'uid' => 3, 'uid' => 3,
'name' => 'a', 'name' => 'a',
'version' => '0.6', 'version' => '0.6',
), )),
),
) )
))); )));
$pool = $this->getMock('Composer\DependencyResolver\Pool');
$pool->expects($this->any())
->method('isPackageAcceptable')
->will($this->returnValue(true));
$versionParser = new VersionParser(); $versionParser = new VersionParser();
$repo->setRootAliases(array(
'a' => array(
$versionParser->normalize('0.6') => array('alias' => 'dev-feature', 'alias_normalized' => $versionParser->normalize('dev-feature')),
$versionParser->normalize('1.1.x-dev') => array('alias' => '1.0', 'alias_normalized' => $versionParser->normalize('1.0')),
),
));
$that = $this; $packages = $repo->whatProvides($pool, 'a');
$packages = $repo->loadRecursively(array('a'), function ($name, $stability) use ($that) {
$that->assertEquals('a', $name);
return true;
});
$this->assertCount(5, $packages); $this->assertCount(7, $packages);
$this->assertEquals(array('1.0.x-dev', 'dev-master', '1.1.x-dev', 'dev-develop', '0.6'), array_map(function ($p) { $this->assertEquals(array('1', '1-alias', '2', '2-alias', '2-root', '3', '3-root'), array_keys($packages));
return $p->getPrettyVersion(); $this->assertInstanceOf('Composer\Package\AliasPackage', $packages['2-root']);
}, $packages)); $this->assertSame($packages['2'], $packages['2-root']->getAliasOf());
$this->assertInstanceOf('Composer\Package\AliasPackage', $packages[2]); $this->assertSame($packages['2'], $packages['2-alias']->getAliasOf());
$this->assertSame($packages[3], $packages[2]->getAliasOf());
} }
} }