diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 3ca7eb9e4..a99ea79a0 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -16,6 +16,7 @@ use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; use Composer\IO\NullIO; +use Composer\Exception\IrrecoverableDownloadException; use Composer\Package\Comparer\Comparer; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; @@ -219,6 +220,10 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface } $self->clearLastCacheWrite($package); + if ($e instanceof IrrecoverableDownloadException) { + throw $e; + } + if ($e instanceof TransportException) { // if we got an http response with a proper code, then requesting again will probably not help, abort if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) { diff --git a/src/Composer/Util/HttpDownloader.php b/src/Composer/Util/HttpDownloader.php index 757e5f3c6..ba7a49798 100644 --- a/src/Composer/Util/HttpDownloader.php +++ b/src/Composer/Util/HttpDownloader.php @@ -19,6 +19,7 @@ use Composer\Util\Http\Response; use Composer\Composer; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\Constraint; +use Composer\Exception\IrrecoverableDownloadException; use React\Promise\Promise; /** @@ -257,10 +258,11 @@ class HttpDownloader if (isset($job['curl_id'])) { $curl->abortRequest($job['curl_id']); } + throw new IrrecoverableDownloadException('Download of ' . Url::sanitize($job['request']['url']) . ' canceled'); }; $promise = new Promise($resolver, $canceler); - $promise->then(function ($response) use (&$job, $downloader) { + $promise = $promise->then(function ($response) use (&$job, $downloader) { $job['status'] = HttpDownloader::STATUS_COMPLETED; $job['response'] = $response; @@ -306,7 +308,7 @@ class HttpDownloader if (isset($job['request']['options']['http']['header']) && false !== stripos(implode('', $job['request']['options']['http']['header']), 'if-modified-since')) { $resolve(new Response(array('url' => $url), 304, array(), '')); } else { - $e = new TransportException('Network disabled, request canceled: '.$url, 499); + $e = new TransportException('Network disabled, request canceled: '.Url::sanitize($url), 499); $e->setStatusCode(499); $reject($e); } @@ -429,7 +431,7 @@ class HttpDownloader } } - $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].''); + $io->writeError('<'.$type.'>'.ucfirst($type).' from '.Url::sanitize($url).': '.$data[$type].''); } } diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index f940f49a9..f2f286916 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -177,6 +177,8 @@ class ProcessExecutor // signal can throw in various conditions, but we don't care if it fails } $job['process']->stop(1); + + throw new \RuntimeException('Aborted process'); }; $promise = new Promise($resolver, $canceler);