diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 9fa498af8..7d44142d7 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -106,6 +106,12 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface throw new \InvalidArgumentException('The given package is missing url information'); } + $cacheKeyGenerator = function (PackageInterface $package, $key) { + $cacheKey = sha1($key); + + return $package->getName().'/'.$cacheKey.'.'.$package->getDistType(); + }; + $retries = 3; $urls = $package->getDistUrls(); foreach ($urls as $index => $url) { @@ -113,7 +119,11 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface $urls[$index] = array( 'base' => $url, 'processed' => $processedUrl, - 'cacheKey' => $this->getCacheKey($package, $processedUrl) + // we use the complete download url here to avoid conflicting entries + // from different packages, which would potentially allow a given package + // in a third party repo to pre-populate the cache for the same package in + // packagist for example. + 'cacheKey' => $cacheKeyGenerator($package, $processedUrl) ); } @@ -130,12 +140,17 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface $accept = null; $reject = null; - $download = function () use ($io, $output, $httpDownloader, $cache, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) { + $download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) { $url = reset($urls); if ($eventDispatcher) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $httpDownloader, $url['processed'], 'package', $package); $eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); + if ($preFileDownloadEvent->getCustomCacheKey() !== null) { + $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getCustomCacheKey()); + } else if ($preFileDownloadEvent->getProcessedUrl() !== $url['processed']) { + $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getProcessedUrl()); + } $url['processed'] = $preFileDownloadEvent->getProcessedUrl(); } @@ -398,17 +413,6 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface return $url; } - private function getCacheKey(PackageInterface $package, $processedUrl) - { - // we use the complete download url here to avoid conflicting entries - // from different packages, which would potentially allow a given package - // in a third party repo to pre-populate the cache for the same package in - // packagist for example. - $cacheKey = sha1($processedUrl); - - return $package->getName().'/'.$cacheKey.'.'.$package->getDistType(); - } - /** * {@inheritDoc} * @throws \RuntimeException diff --git a/src/Composer/Plugin/PreFileDownloadEvent.php b/src/Composer/Plugin/PreFileDownloadEvent.php index f7b523b94..0f83b3178 100644 --- a/src/Composer/Plugin/PreFileDownloadEvent.php +++ b/src/Composer/Plugin/PreFileDownloadEvent.php @@ -32,6 +32,11 @@ class PreFileDownloadEvent extends Event */ private $processedUrl; + /** + * @var string|null + */ + private $customCacheKey; + /** * @var string */ @@ -88,6 +93,26 @@ class PreFileDownloadEvent extends Event $this->processedUrl = $processedUrl; } + /** + * Retrieves a custom package cache key for this download. + * + * @return string|null + */ + public function getCustomCacheKey() + { + return $this->customCacheKey; + } + + /** + * Sets a custom package cache key for this download. + * + * @param string|null $customCacheKey New cache key + */ + public function setCustomCacheKey($customCacheKey) + { + $this->customCacheKey = $customCacheKey; + } + /** * Returns the type of this download (package, metadata). *