diff --git a/src/Composer/Downloader/ArchiveDownloader.php b/src/Composer/Downloader/ArchiveDownloader.php
index abe1b6884..8f7d751a3 100644
--- a/src/Composer/Downloader/ArchiveDownloader.php
+++ b/src/Composer/Downloader/ArchiveDownloader.php
@@ -28,14 +28,14 @@ abstract class ArchiveDownloader extends FileDownloader
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path)
+ public function download(PackageInterface $package, $path, $output = true)
{
$temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
$retries = 3;
while ($retries--) {
- $fileName = parent::download($package, $path);
+ $fileName = parent::download($package, $path, $output);
- $this->io->writeError(' Extracting archive', true, IOInterface::VERBOSE);
+ $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
try {
$this->filesystem->ensureDirectoryExists($temporaryDir);
@@ -76,6 +76,7 @@ abstract class ArchiveDownloader extends FileDownloader
// retry downloading if we have an invalid zip file
if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
+ $this->io->writeError('');
if ($this->io->isDebug()) {
$this->io->writeError(' Invalid zip file ('.$e->getMessage().'), retrying...');
} else {
@@ -91,7 +92,9 @@ abstract class ArchiveDownloader extends FileDownloader
break;
}
- $this->io->writeError('');
+ if ($output) {
+ $this->io->writeError('');
+ }
}
/**
diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php
index 4d35b31a3..8c8c13bc0 100644
--- a/src/Composer/Downloader/FileDownloader.php
+++ b/src/Composer/Downloader/FileDownloader.php
@@ -77,13 +77,15 @@ class FileDownloader implements DownloaderInterface
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path)
+ public function download(PackageInterface $package, $path, $output = true)
{
if (!$package->getDistUrl()) {
throw new \InvalidArgumentException('The given package is missing url information');
}
- $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ if ($output) {
+ $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")", false);
+ }
$urls = $package->getDistUrls();
while ($url = array_shift($urls)) {
@@ -95,7 +97,7 @@ class FileDownloader implements DownloaderInterface
$this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
} elseif (count($urls)) {
$this->io->writeError('');
- $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')');
+ $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
}
if (!count($urls)) {
@@ -104,7 +106,9 @@ class FileDownloader implements DownloaderInterface
}
}
- $this->io->writeError('');
+ if ($output) {
+ $this->io->writeError('');
+ }
}
protected function doDownload(PackageInterface $package, $path, $url)
@@ -129,7 +133,7 @@ class FileDownloader implements DownloaderInterface
// download if we don't have it in cache or the cache is invalidated
if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
if (!$this->outputProgress) {
- $this->io->writeError(' Downloading');
+ $this->io->writeError(' Downloading', false);
}
// try to download 3 times then fail hard
@@ -143,6 +147,7 @@ class FileDownloader implements DownloaderInterface
if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
throw $e;
}
+ $this->io->writeError('');
$this->io->writeError(' Download failed, retrying...', true, IOInterface::VERBOSE);
usleep(500000);
}
@@ -153,7 +158,7 @@ class FileDownloader implements DownloaderInterface
$this->cache->copyFrom($cacheKey, $fileName);
}
} else {
- $this->io->writeError(' Loading from cache');
+ $this->io->writeError(' Loading from cache', false);
}
if (!file_exists($fileName)) {
@@ -197,16 +202,26 @@ class FileDownloader implements DownloaderInterface
*/
public function update(PackageInterface $initial, PackageInterface $target, $path)
{
- $this->remove($initial, $path);
- $this->download($target, $path);
+ $name = $target->getName();
+ $from = $initial->getPrettyVersion();
+ $to = $target->getPrettyVersion();
+
+ $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . ")", false);
+
+ $this->remove($initial, $path, false);
+ $this->download($target, $path, false);
+
+ $this->io->writeError('');
}
/**
* {@inheritDoc}
*/
- public function remove(PackageInterface $package, $path)
+ public function remove(PackageInterface $package, $path, $output = true)
{
- $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ if ($output) {
+ $this->io->writeError(" - Removing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ }
if (!$this->filesystem->removeDirectory($path)) {
throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
}
diff --git a/src/Composer/Downloader/FossilDownloader.php b/src/Composer/Downloader/FossilDownloader.php
index fd8a7f554..72b09ce8c 100644
--- a/src/Composer/Downloader/FossilDownloader.php
+++ b/src/Composer/Downloader/FossilDownloader.php
@@ -31,7 +31,7 @@ class FossilDownloader extends VcsDownloader
$url = ProcessExecutor::escape($url);
$ref = ProcessExecutor::escape($package->getSourceReference());
$repoFile = $path . '.fossil';
- $this->io->writeError(" Cloning ".$package->getSourceReference());
+ $this->io->writeError(" Cloning ".$package->getSourceReference());
$command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
if (0 !== $this->process->execute($command, $ignoredOutput)) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
@@ -56,7 +56,7 @@ class FossilDownloader extends VcsDownloader
$url = ProcessExecutor::escape($url);
$ref = ProcessExecutor::escape($target->getSourceReference());
- $this->io->writeError(" Updating to ".$target->getSourceReference());
+ $this->io->writeError(" Updating to ".$target->getSourceReference());
if (!$this->hasMetadataRepository($path)) {
throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php
index 5acc5fed6..6d87394bc 100644
--- a/src/Composer/Downloader/GitDownloader.php
+++ b/src/Composer/Downloader/GitDownloader.php
@@ -49,14 +49,15 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
// --dissociate option is only available since git 2.3.0-rc0
$gitVersion = $this->gitUtil->getVersion();
- $msg = " Cloning ".$ref;
+ $msg = " Cloning ".$ref;
if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
+ $this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
try {
$this->gitUtil->syncMirror($url, $cachePath);
if (is_dir($cachePath)) {
$cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath));
- $msg = " Cloning ".$ref.' from cache';
+ $msg = " Cloning ".$ref.' from cache';
}
} catch (\RuntimeException $e) {}
}
@@ -104,7 +105,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
}
$ref = $target->getSourceReference();
- $this->io->writeError(" Checking out ".$ref);
+ $this->io->writeError(" Checking out ".$ref);
$command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s^{commit} || (git fetch composer && git fetch --tags composer)';
$commandCallable = function ($url) use ($command, $ref) {
diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php
index 4222282c0..a69d654ae 100644
--- a/src/Composer/Downloader/HgDownloader.php
+++ b/src/Composer/Downloader/HgDownloader.php
@@ -30,7 +30,7 @@ class HgDownloader extends VcsDownloader
$url = ProcessExecutor::escape($url);
$ref = ProcessExecutor::escape($package->getSourceReference());
- $this->io->writeError(" Cloning ".$package->getSourceReference());
+ $this->io->writeError(" Cloning ".$package->getSourceReference());
$command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
if (0 !== $this->process->execute($command, $ignoredOutput)) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
@@ -51,7 +51,7 @@ class HgDownloader extends VcsDownloader
$url = ProcessExecutor::escape($url);
$ref = ProcessExecutor::escape($target->getSourceReference());
- $this->io->writeError(" Updating to ".$target->getSourceReference());
+ $this->io->writeError(" Updating to ".$target->getSourceReference());
if (!$this->hasMetadataRepository($path)) {
throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php
index 6505d1f02..cde32f4a6 100644
--- a/src/Composer/Downloader/PathDownloader.php
+++ b/src/Composer/Downloader/PathDownloader.php
@@ -35,7 +35,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
/**
* {@inheritdoc}
*/
- public function download(PackageInterface $package, $path)
+ public function download(PackageInterface $package, $path, $output = true)
{
$url = $package->getDistUrl();
$realUrl = realpath($url);
@@ -75,18 +75,21 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
$fileSystem = new Filesystem();
$this->filesystem->removeDirectory($path);
- $this->io->writeError(sprintf(
- ' - Installing %s (%s)',
- $package->getName(),
- $package->getFullPrettyVersion()
- ));
+ if ($output) {
+ $this->io->writeError(sprintf(
+ ' - Installing %s (%s)',
+ $package->getName(),
+ $package->getFullPrettyVersion()
+ ), false);
+ }
+ $isFallback = false;
if (self::STRATEGY_SYMLINK == $currentStrategy) {
try {
if (Platform::isWindows()) {
// Implement symlinks as NTFS junctions on Windows
$this->filesystem->junction($realUrl, $path);
- $this->io->writeError(sprintf(' Junctioned from %s', $url));
+ $this->io->writeError(sprintf(' Junctioned from %s', $url), false);
} else {
$absolutePath = $path;
if (!$this->filesystem->isAbsolutePath($absolutePath)) {
@@ -95,12 +98,14 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
$shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
$path = rtrim($path, "/");
$fileSystem->symlink($shortestPath, $path);
- $this->io->writeError(sprintf(' Symlinked from %s', $url));
+ $this->io->writeError(sprintf(' Symlinked from %s', $url), false);
}
} catch (IOException $e) {
if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
+ $this->io->writeError('');
$this->io->writeError(' Symlink failed, fallback to use mirroring!');
$currentStrategy = self::STRATEGY_MIRROR;
+ $isFallback = true;
} else {
throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
}
@@ -110,7 +115,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
// Fallback if symlink failed or if symlink is not allowed for the package
if (self::STRATEGY_MIRROR == $currentStrategy) {
$fileSystem->mirror($realUrl, $path);
- $this->io->writeError(sprintf(' Mirrored from %s', $url));
+ $this->io->writeError(sprintf('%s Mirrored from %s', $isFallback ? ' ' : '', $url), false);
}
$this->io->writeError('');
@@ -119,7 +124,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
/**
* {@inheritDoc}
*/
- public function remove(PackageInterface $package, $path)
+ public function remove(PackageInterface $package, $path, $output = true)
{
/**
* For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process
@@ -127,9 +132,11 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
* is disastrous within a junction. So in that case we have no other real choice but to fail hard.
*/
if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
- $this->io->writeError(" - Removing junction for " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ if ($output) {
+ $this->io->writeError(" - Removing junction for " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ }
if (!$this->filesystem->removeJunction($path)) {
- $this->io->writeError("Could not remove junction at " . $path . " - is another process locking it?");
+ $this->io->writeError(" Could not remove junction at " . $path . " - is another process locking it?");
throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
}
} else {
diff --git a/src/Composer/Downloader/PerforceDownloader.php b/src/Composer/Downloader/PerforceDownloader.php
index 6b01bf516..ff1cc10c6 100644
--- a/src/Composer/Downloader/PerforceDownloader.php
+++ b/src/Composer/Downloader/PerforceDownloader.php
@@ -32,7 +32,7 @@ class PerforceDownloader extends VcsDownloader
$ref = $package->getSourceReference();
$label = $this->getLabelFromSourceReference($ref);
- $this->io->writeError(' Cloning ' . $ref);
+ $this->io->writeError(' Cloning ' . $ref);
$this->initPerforce($package, $path, $url);
$this->perforce->setStream($ref);
$this->perforce->p4Login();
diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php
index a21f35858..b3c8c33d8 100644
--- a/src/Composer/Downloader/SvnDownloader.php
+++ b/src/Composer/Downloader/SvnDownloader.php
@@ -40,7 +40,7 @@ class SvnDownloader extends VcsDownloader
}
}
- $this->io->writeError(" Checking out ".$package->getSourceReference());
+ $this->io->writeError(" Checking out ".$package->getSourceReference());
$this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
}
@@ -63,7 +63,7 @@ class SvnDownloader extends VcsDownloader
}
}
- $this->io->writeError(" Checking out " . $ref);
+ $this->io->writeError(" Checking out " . $ref);
$this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
}
diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php
index 75334efed..f779bead1 100644
--- a/src/Composer/Downloader/VcsDownloader.php
+++ b/src/Composer/Downloader/VcsDownloader.php
@@ -60,7 +60,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
}
- $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ $this->io->writeError(" - Installing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")", false);
$this->filesystem->emptyDirectory($path);
$urls = $package->getSourceUrls();
@@ -104,8 +104,6 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
}
}
}
-
- $this->io->writeError('');
}
/**
@@ -132,7 +130,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
$to = $target->getFullPrettyVersion();
}
- $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . ")");
+ $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . ")", false);
$this->cleanChanges($initial, $path, true);
$urls = $target->getSourceUrls();
@@ -189,8 +187,6 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
if (!$urls && $exception) {
throw $exception;
}
-
- $this->io->writeError('');
}
/**
diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php
index 99fecdf0e..612eb9da2 100644
--- a/src/Composer/Downloader/ZipDownloader.php
+++ b/src/Composer/Downloader/ZipDownloader.php
@@ -41,7 +41,7 @@ class ZipDownloader extends ArchiveDownloader
/**
* {@inheritDoc}
*/
- public function download(PackageInterface $package, $path)
+ public function download(PackageInterface $package, $path, $output = true)
{
if (null === self::$hasSystemUnzip) {
$finder = new ExecutableFinder;
@@ -56,7 +56,7 @@ class ZipDownloader extends ArchiveDownloader
throw new \RuntimeException($error);
}
- return parent::download($package, $path);
+ return parent::download($package, $path, $output);
}
protected function extract($file, $path)
diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php
index 30c9ce1b6..3f619aef4 100644
--- a/src/Composer/Installer.php
+++ b/src/Composer/Installer.php
@@ -577,10 +577,8 @@ class Installer
// output non-alias ops when not executing operations (i.e. dry run), output alias ops in debug verbosity
if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
$this->io->writeError(' - ' . $operation);
- $this->io->writeError('');
} elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
$this->io->writeError(' - ' . $operation);
- $this->io->writeError('');
}
$this->installationManager->execute($localRepo, $operation);
diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php
index 9bfb1e2dd..f482c91b9 100644
--- a/src/Composer/Util/RemoteFilesystem.php
+++ b/src/Composer/Util/RemoteFilesystem.php
@@ -276,7 +276,7 @@ class RemoteFilesystem
}
if ($this->progress && !$isRedirect) {
- $this->io->writeError(" Downloading: Connecting...", false);
+ $this->io->writeError(" Downloading: Connecting...", false);
}
$errorMessage = '';
@@ -325,6 +325,7 @@ class RemoteFilesystem
if (isset($e) && !$this->retry) {
if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
$this->degradedMode = true;
+ $this->io->writeError('');
$this->io->writeError(array(
''.$e->getMessage().'',
'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info',
@@ -366,7 +367,7 @@ class RemoteFilesystem
if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
if (!$this->retry) {
if ($this->progress && !$this->retry && !$isRedirect) {
- $this->io->overwriteError(" Downloading: Failed");
+ $this->io->overwriteError(" Downloading: Failed", false);
}
$e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
@@ -379,7 +380,7 @@ class RemoteFilesystem
}
if ($this->progress && !$this->retry && !$isRedirect) {
- $this->io->overwriteError(" Downloading: ".($result === false ? 'Failed' : '100%'));
+ $this->io->overwriteError(" Downloading: ".($result === false ? 'Failed' : '100%'), false);
}
// decode gzip
@@ -405,6 +406,7 @@ class RemoteFilesystem
$this->degradedMode = true;
$this->io->writeError(array(
+ '',
'Failed to decode response: '.$e->getMessage().'',
'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info',
));
@@ -461,6 +463,7 @@ class RemoteFilesystem
$this->retry = true;
}
} else {
+ $this->io->writeError('');
$this->io->writeError(sprintf(
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
PHP_VERSION
@@ -490,6 +493,7 @@ class RemoteFilesystem
if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
$this->degradedMode = true;
+ $this->io->writeError('');
$this->io->writeError(array(
''.$e->getMessage().'',
'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info',
@@ -563,7 +567,7 @@ class RemoteFilesystem
if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
$this->lastProgress = $progression;
- $this->io->overwriteError(" Downloading: $progression%", false);
+ $this->io->overwriteError(" Downloading: $progression%", false);
}
}
break;
@@ -638,7 +642,8 @@ class RemoteFilesystem
throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
}
- $this->io->overwriteError(' Authentication required ('.parse_url($this->fileUrl, PHP_URL_HOST).'):');
+ $this->io->overwriteError('');
+ $this->io->writeError(' Authentication required ('.parse_url($this->fileUrl, PHP_URL_HOST).'):');
$username = $this->io->ask(' Username: ');
$password = $this->io->askAndHideAnswer(' Password: ');
$this->io->setAuthentication($this->originUrl, $username, $password);
@@ -681,6 +686,7 @@ class RemoteFilesystem
// Handle subjectAltName on lesser PHP's.
$certMap = $this->peerCertificateMap[$urlAuthority];
+ $this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf(
'Using %s as CN for subjectAltName enabled host %s',
$certMap['cn'],
@@ -766,6 +772,7 @@ class RemoteFilesystem
if (!empty($targetUrl)) {
$this->redirects++;
+ $this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
$additionalOptions['redirects'] = $this->redirects;
diff --git a/tests/Composer/Test/Fixtures/functional/create-project-command.test b/tests/Composer/Test/Fixtures/functional/create-project-command.test
index bdb04303c..d6ce7b077 100644
--- a/tests/Composer/Test/Fixtures/functional/create-project-command.test
+++ b/tests/Composer/Test/Fixtures/functional/create-project-command.test
@@ -2,9 +2,7 @@
create-project seld/jsonlint %testDir% 1.0.0 --prefer-source -n
--EXPECT-ERROR--
Installing seld/jsonlint (1.0.0)
- - Installing seld/jsonlint (1.0.0)
- Cloning 3b4bc2a96ff5d3fe6866bfe9dd0c845246705791
-
+ - Installing seld/jsonlint (1.0.0) Cloning 3b4bc2a96ff5d3fe6866bfe9dd0c845246705791
Created project in %testDir%
Loading composer repositories with package information
Updating dependencies (including require-dev)