From 4d082f77b85a2365751bbbcff69fe46cab4c11b1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 6 Dec 2016 23:41:46 +0100 Subject: [PATCH] Simplify composer output to take less lines --- src/Composer/Downloader/ArchiveDownloader.php | 11 +++--- src/Composer/Downloader/FileDownloader.php | 35 +++++++++++++------ src/Composer/Downloader/FossilDownloader.php | 4 +-- src/Composer/Downloader/GitDownloader.php | 7 ++-- src/Composer/Downloader/HgDownloader.php | 4 +-- src/Composer/Downloader/PathDownloader.php | 31 +++++++++------- .../Downloader/PerforceDownloader.php | 2 +- src/Composer/Downloader/SvnDownloader.php | 4 +-- src/Composer/Downloader/VcsDownloader.php | 8 ++--- src/Composer/Downloader/ZipDownloader.php | 4 +-- src/Composer/Installer.php | 2 -- src/Composer/Util/RemoteFilesystem.php | 17 ++++++--- .../functional/create-project-command.test | 4 +-- 13 files changed, 79 insertions(+), 54 deletions(-) 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 35dfa5cb7..c56e0435f 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($repoFile)); + $this->io->writeError(" Cloning ".$package->getSourceReference($repoFile)); $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 caae429e9..b8badecf6 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -575,10 +575,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)