diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index d3ecec03d..67b429837 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -33,6 +33,7 @@ class RemoteFilesystem private $progress; private $lastProgress; private $options; + private $retryAuthFailure; /** * Constructor. @@ -109,12 +110,19 @@ class RemoteFilesystem $this->fileName = $fileName; $this->progress = $progress; $this->lastProgress = null; + $this->retryAuthFailure = true; // capture username/password from URL if there is one if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) { $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2])); } + if (isset($additionalOptions['retry-auth-failure'])) { + $this->retryAuthFailure = (bool) $additionalOptions['retry-auth-failure']; + + unset($additionalOptions['retry-auth-failure']); + } + $options = $this->getOptionsForUrl($originUrl, $additionalOptions); if ($this->io->isDebug()) { @@ -247,6 +255,11 @@ class RemoteFilesystem throw new TransportException($message, 401); } + // Bail if the caller is going to handle authentication failures itself. + if (!$this->retryAuthFailure) { + throw new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.trim($message).')', 401); + } + $this->promptAuthAndRetry(); break; }