diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index b23d5aced..07eff48eb 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -65,6 +65,12 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito private $rootData; private $hasPartialPackages; private $partialPackagesByName; + + /** + * @var array list of package names which returned a 404 and should not be re-fetched in case loadPackage is called several times + * useful for v2 metadata repositories with lazy providers + */ + private $packagesNotFoundCache = array(); /** * TODO v3 should make this private once we can drop PHP 5.3 support * @private @@ -1079,6 +1085,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito { $retries = 3; + if (isset($this->packagesNotFoundCache[$filename])) { + return \React\Promise\Util::promiseFor(array('packages' => array())); + } + $httpDownloader = $this->httpDownloader; if ($this->eventDispatcher) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename); @@ -1095,6 +1105,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito $accept = function ($response) use ($io, $url, $cache, $cacheKey) { // package not found is acceptable for a v2 protocol repository if ($response->getStatusCode() === 404) { + $this->packagesNotFoundCache[$filename] = true; return array('packages' => array()); } @@ -1119,6 +1130,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito $reject = function ($e) use (&$retries, $httpDownloader, $filename, $options, &$reject, $accept, $io, $url, &$degradedMode) { if ($e instanceof TransportException && $e->getStatusCode() === 404) { + $this->packagesNotFoundCache[$filename] = true; return false; }