Browse Source

Add verbosity input support to IOInterface

Jordi Boggiano 9 years ago
parent
commit
49d7d65933
31 changed files with 181 additions and 219 deletions
  1. 4 12
      src/Composer/Cache.php
  2. 9 9
      src/Composer/Command/ShowCommand.php
  3. 6 8
      src/Composer/Console/Application.php
  4. 2 3
      src/Composer/Downloader/ArchiveDownloader.php
  5. 1 3
      src/Composer/Downloader/FileDownloader.php
  6. 1 3
      src/Composer/EventDispatcher/EventDispatcher.php
  7. 3 9
      src/Composer/Factory.php
  8. 1 1
      src/Composer/IO/BufferIO.php
  9. 32 17
      src/Composer/IO/ConsoleIO.php
  10. 24 14
      src/Composer/IO/IOInterface.php
  11. 4 4
      src/Composer/IO/NullIO.php
  12. 4 8
      src/Composer/Installer.php
  13. 1 3
      src/Composer/Installer/PearInstaller.php
  14. 1 3
      src/Composer/Plugin/PluginManager.php
  15. 3 7
      src/Composer/Repository/ArtifactRepository.php
  16. 1 3
      src/Composer/Repository/PearRepository.php
  17. 1 3
      src/Composer/Repository/Vcs/GitBitbucketDriver.php
  18. 1 3
      src/Composer/Repository/Vcs/GitHubDriver.php
  19. 1 3
      src/Composer/Repository/Vcs/GitLabDriver.php
  20. 1 3
      src/Composer/Repository/Vcs/HgBitbucketDriver.php
  21. 8 16
      src/Composer/Util/RemoteFilesystem.php
  22. 9 0
      tests/Composer/Test/ApplicationTest.php
  23. 15 42
      tests/Composer/Test/EventDispatcher/EventDispatcherTest.php
  24. 4 4
      tests/Composer/Test/Fixtures/installer/abandoned-listed.test
  25. 3 3
      tests/Composer/Test/Fixtures/installer/broken-deps-do-not-replace.test
  26. 4 4
      tests/Composer/Test/Fixtures/installer/suggest-installed.test
  27. 4 4
      tests/Composer/Test/Fixtures/installer/suggest-prod.test
  28. 4 4
      tests/Composer/Test/Fixtures/installer/suggest-replaced.test
  29. 4 4
      tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test
  30. 20 7
      tests/Composer/Test/IO/ConsoleIOTest.php
  31. 5 12
      tests/Composer/Test/InstallerTest.php

+ 4 - 12
src/Composer/Cache.php

@@ -67,9 +67,7 @@ class Cache
     {
         $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
         if ($this->enabled && file_exists($this->root . $file)) {
-            if ($this->io->isDebug()) {
-                $this->io->writeError('Reading '.$this->root . $file.' from cache');
-            }
+            $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
 
             return file_get_contents($this->root . $file);
         }
@@ -82,16 +80,12 @@ class Cache
         if ($this->enabled) {
             $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
 
-            if ($this->io->isDebug()) {
-                $this->io->writeError('Writing '.$this->root . $file.' into cache');
-            }
+            $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
 
             try {
                 return file_put_contents($this->root . $file, $contents);
             } catch (\ErrorException $e) {
-                if ($this->io->isDebug()) {
-                    $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>');
-                }
+                $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
                 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
                     // Remove partial file.
                     unlink($this->root . $file);
@@ -152,9 +146,7 @@ class Cache
                 touch($this->root . $file);
             }
 
-            if ($this->io->isDebug()) {
-                $this->io->writeError('Reading '.$this->root . $file.' from cache');
-            }
+            $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
 
             return copy($this->root . $file, $target);
         }

+ 9 - 9
src/Composer/Command/ShowCommand.php

@@ -246,10 +246,10 @@ EOT
                 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
                 foreach ($packages[$type] as $package) {
                     if (is_object($package)) {
-                        $output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
+                        $io->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
 
                         if ($writeVersion) {
-                            $output->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false);
+                            $io->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false);
                         }
 
                         if ($writeDescription) {
@@ -258,15 +258,15 @@ EOT
                             if (strlen($description) > $remaining) {
                                 $description = substr($description, 0, $remaining - 3) . '...';
                             }
-                            $output->write(' ' . $description);
+                            $io->write(' ' . $description, false);
                         }
 
                         if ($writePath) {
                             $path = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
-                            $output->write(' ' . $path);
+                            $io->write(' ' . $path, false);
                         }
                     } else {
-                        $output->write($indent . $package);
+                        $io->write($indent . $package, false);
                     }
                     $io->write('');
                 }
@@ -489,10 +489,10 @@ EOT
         $packagesInTree = array();
         $packagesInTree[] = $package;
 
-        $output->write(sprintf('<info>%s</info>', $package->getPrettyName()));
-        $output->write(' ' . $package->getPrettyVersion());
-        $output->write(' ' . strtok($package->getDescription(), "\r\n"));
-        $output->writeln('');
+        $io = $this->getIO();
+        $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
+        $io->write(' ' . $package->getPrettyVersion(), false);
+        $io->write(' ' . strtok($package->getDescription(), "\r\n"));
 
         if (is_object($package)) {
             $requires = $package->getRequires();

+ 6 - 8
src/Composer/Console/Application.php

@@ -136,9 +136,7 @@ class Application extends BaseApplication
             if ($newWorkDir = $this->getNewWorkingDir($input)) {
                 $oldWorkingDir = getcwd();
                 chdir($newWorkDir);
-                if ($io->isDebug() >= 4) {
-                    $io->writeError('Changed CWD to ' . getcwd());
-                }
+                $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
             }
 
             // add non-standard scripts as own commands
@@ -214,7 +212,7 @@ class Application extends BaseApplication
                     || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
                     || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
                 ) {
-                    $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>');
+                    $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
                 }
             }
         } catch (\Exception $e) {
@@ -222,13 +220,13 @@ class Application extends BaseApplication
         Silencer::restore();
 
         if (defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
-            $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>');
-            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>');
+            $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
+            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>', true, IOInterface::QUIET);
         }
 
         if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
-            $io->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>');
-            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>');
+            $io->writeError('<error>The following exception is caused by a lack of memory and not having swap configured</error>', true, IOInterface::QUIET);
+            $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
         }
     }
 

+ 2 - 3
src/Composer/Downloader/ArchiveDownloader.php

@@ -14,6 +14,7 @@ namespace Composer\Downloader;
 
 use Composer\Package\PackageInterface;
 use Symfony\Component\Finder\Finder;
+use Composer\IO\IOInterface;
 
 /**
  * Base downloader for archives
@@ -34,9 +35,7 @@ abstract class ArchiveDownloader extends FileDownloader
         while ($retries--) {
             $fileName = parent::download($package, $path);
 
-            if ($this->io->isVerbose()) {
-                $this->io->writeError('    Extracting archive');
-            }
+            $this->io->writeError('    Extracting archive', true, IOInterface::VERBOSE);
 
             try {
                 $this->filesystem->ensureDirectoryExists($temporaryDir);

+ 1 - 3
src/Composer/Downloader/FileDownloader.php

@@ -141,9 +141,7 @@ class FileDownloader implements DownloaderInterface
                         if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
                             throw $e;
                         }
-                        if ($this->io->isVerbose()) {
-                            $this->io->writeError('    Download failed, retrying...');
-                        }
+                        $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
                         usleep(500000);
                     }
                 }

+ 1 - 3
src/Composer/EventDispatcher/EventDispatcher.php

@@ -155,9 +155,7 @@ class EventDispatcher
                 $event = $this->checkListenerExpectedEvent($callable, $event);
                 $return = false === call_user_func($callable, $event) ? 1 : 0;
             } elseif ($this->isComposerScript($callable)) {
-                if ($this->io->isVerbose()) {
-                    $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable));
-                }
+                $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
                 $scriptName = substr($callable, 1);
                 $args = $event->getArguments();
                 $flags = $event->getFlags();

+ 3 - 9
src/Composer/Factory.php

@@ -293,14 +293,10 @@ class Factory
         $config = static::createConfig($io, $cwd);
         $config->merge($localConfig);
         if (isset($composerFile)) {
-            if ($io && $io->isDebug()) {
-                $io->writeError('Loading config file ' . $composerFile);
-            }
+            $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
             $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json');
             if ($localAuthFile->exists()) {
-                if ($io && $io->isDebug()) {
-                    $io->writeError('Loading config file ' . $localAuthFile->getPath());
-                }
+                $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
                 $config->merge(array('config' => $localAuthFile->read()));
                 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
             }
@@ -435,9 +431,7 @@ class Factory
         try {
             $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), false);
         } catch (\Exception $e) {
-            if ($io->isDebug()) {
-                $io->writeError('Failed to initialize global composer: '.$e->getMessage());
-            }
+            $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
         }
 
         return $composer;

+ 1 - 1
src/Composer/IO/BufferIO.php

@@ -35,7 +35,7 @@ class BufferIO extends ConsoleIO
         $input = new StringInput($input);
         $input->setInteractive(false);
 
-        $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, !empty($formatter), $formatter);
+        $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
 
         parent::__construct($input, $output, new HelperSet(array()));
     }

+ 32 - 17
src/Composer/IO/ConsoleIO.php

@@ -33,6 +33,7 @@ class ConsoleIO extends BaseIO
     protected $lastMessage;
     protected $lastMessageErr;
     private $startTime;
+    private $verbosityMap;
 
     /**
      * Constructor.
@@ -46,6 +47,13 @@ class ConsoleIO extends BaseIO
         $this->input = $input;
         $this->output = $output;
         $this->helperSet = $helperSet;
+        $this->verbosityMap = array(
+            self::QUIET => OutputInterface::VERBOSITY_QUIET,
+            self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
+            self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
+            self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
+            self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
+        );
     }
 
     public function enableDebugging($startTime)
@@ -96,26 +104,32 @@ class ConsoleIO extends BaseIO
     /**
      * {@inheritDoc}
      */
-    public function write($messages, $newline = true)
+    public function write($messages, $newline = true, $verbosity = self::NORMAL)
     {
-        $this->doWrite($messages, $newline, false);
+        $this->doWrite($messages, $newline, false, $verbosity);
     }
 
     /**
      * {@inheritDoc}
      */
-    public function writeError($messages, $newline = true)
+    public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
     {
-        $this->doWrite($messages, $newline, true);
+        $this->doWrite($messages, $newline, true, $verbosity);
     }
 
     /**
      * @param array|string $messages
      * @param bool         $newline
      * @param bool         $stderr
+     * @param int          $verbosity
      */
-    private function doWrite($messages, $newline, $stderr)
+    private function doWrite($messages, $newline, $stderr, $verbosity)
     {
+        $sfVerbosity = $this->verbosityMap[$verbosity];
+        if ($sfVerbosity > $this->output->getVerbosity()) {
+            return;
+        }
+
         if (null !== $this->startTime) {
             $memoryUsage = memory_get_usage() / 1024 / 1024;
             $timeSpent = microtime(true) - $this->startTime;
@@ -125,30 +139,30 @@ class ConsoleIO extends BaseIO
         }
 
         if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
-            $this->output->getErrorOutput()->write($messages, $newline);
+            $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
             $this->lastMessageErr = join($newline ? "\n" : '', (array) $messages);
 
             return;
         }
 
-        $this->output->write($messages, $newline);
+        $this->output->write($messages, $newline, $sfVerbosity);
         $this->lastMessage = join($newline ? "\n" : '', (array) $messages);
     }
 
     /**
      * {@inheritDoc}
      */
-    public function overwrite($messages, $newline = true, $size = null)
+    public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
     {
-        $this->doOverwrite($messages, $newline, $size, false);
+        $this->doOverwrite($messages, $newline, $size, false, $verbosity);
     }
 
     /**
      * {@inheritDoc}
      */
-    public function overwriteError($messages, $newline = true, $size = null)
+    public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
     {
-        $this->doOverwrite($messages, $newline, $size, true);
+        $this->doOverwrite($messages, $newline, $size, true, $verbosity);
     }
 
     /**
@@ -156,8 +170,9 @@ class ConsoleIO extends BaseIO
      * @param bool         $newline
      * @param int|null     $size
      * @param bool         $stderr
+     * @param int          $verbosity
      */
-    private function doOverwrite($messages, $newline, $size, $stderr)
+    private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
     {
         // messages can be an array, let's convert it to string anyway
         $messages = join($newline ? "\n" : '', (array) $messages);
@@ -168,21 +183,21 @@ class ConsoleIO extends BaseIO
             $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
         }
         // ...let's fill its length with backspaces
-        $this->doWrite(str_repeat("\x08", $size), false, $stderr);
+        $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
 
         // write the new message
-        $this->doWrite($messages, false, $stderr);
+        $this->doWrite($messages, false, $stderr, $verbosity);
 
         $fill = $size - strlen(strip_tags($messages));
         if ($fill > 0) {
             // whitespace whatever has left
-            $this->doWrite(str_repeat(' ', $fill), false, $stderr);
+            $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
             // move the cursor back
-            $this->doWrite(str_repeat("\x08", $fill), false, $stderr);
+            $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
         }
 
         if ($newline) {
-            $this->doWrite('', true, $stderr);
+            $this->doWrite('', true, $stderr, $verbosity);
         }
 
         if ($stderr) {

+ 24 - 14
src/Composer/IO/IOInterface.php

@@ -21,6 +21,12 @@ use Composer\Config;
  */
 interface IOInterface
 {
+    const QUIET = 1;
+    const NORMAL = 2;
+    const VERBOSE = 4;
+    const VERY_VERBOSE = 8;
+    const DEBUG = 16;
+
     /**
      * Is this input means interactive?
      *
@@ -59,36 +65,40 @@ interface IOInterface
     /**
      * Writes a message to the output.
      *
-     * @param string|array $messages The message as an array of lines or a single string
-     * @param bool         $newline  Whether to add a newline or not
+     * @param string|array $messages  The message as an array of lines or a single string
+     * @param bool         $newline   Whether to add a newline or not
+     * @param int          $verbosity Verbosity level from the VERBOSITY_* constants
      */
-    public function write($messages, $newline = true);
+    public function write($messages, $newline = true, $verbosity = self::NORMAL);
 
     /**
      * Writes a message to the error output.
      *
-     * @param string|array $messages The message as an array of lines or a single string
-     * @param bool         $newline  Whether to add a newline or not
+     * @param string|array $messages  The message as an array of lines or a single string
+     * @param bool         $newline   Whether to add a newline or not
+     * @param int          $verbosity Verbosity level from the VERBOSITY_* constants
      */
-    public function writeError($messages, $newline = true);
+    public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
 
     /**
      * Overwrites a previous message to the output.
      *
-     * @param string|array $messages The message as an array of lines or a single string
-     * @param bool         $newline  Whether to add a newline or not
-     * @param int          $size     The size of line
+     * @param string|array $messages  The message as an array of lines or a single string
+     * @param bool         $newline   Whether to add a newline or not
+     * @param int          $size      The size of line
+     * @param int          $verbosity Verbosity level from the VERBOSITY_* constants
      */
-    public function overwrite($messages, $newline = true, $size = null);
+    public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
 
     /**
      * Overwrites a previous message to the error output.
      *
-     * @param string|array $messages The message as an array of lines or a single string
-     * @param bool         $newline  Whether to add a newline or not
-     * @param int          $size     The size of line
+     * @param string|array $messages  The message as an array of lines or a single string
+     * @param bool         $newline   Whether to add a newline or not
+     * @param int          $size      The size of line
+     * @param int          $verbosity Verbosity level from the VERBOSITY_* constants
      */
-    public function overwriteError($messages, $newline = true, $size = null);
+    public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
 
     /**
      * Asks a question to the user.

+ 4 - 4
src/Composer/IO/NullIO.php

@@ -62,28 +62,28 @@ class NullIO extends BaseIO
     /**
      * {@inheritDoc}
      */
-    public function write($messages, $newline = true)
+    public function write($messages, $newline = true, $verbosity = self::NORMAL)
     {
     }
 
     /**
      * {@inheritDoc}
      */
-    public function writeError($messages, $newline = true)
+    public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
     {
     }
 
     /**
      * {@inheritDoc}
      */
-    public function overwrite($messages, $newline = true, $size = 80)
+    public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
     {
     }
 
     /**
      * {@inheritDoc}
      */
-    public function overwriteError($messages, $newline = true, $size = 80)
+    public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
     {
     }
 

+ 4 - 8
src/Composer/Installer.php

@@ -529,10 +529,8 @@ class Installer
             return max(1, $e->getCode());
         }
 
-        if ($this->io->isVerbose()) {
-            $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies");
-            $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies");
-        }
+        $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
+        $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
 
         // force dev packages to be updated if we update or install from a (potentially new) lock
         $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $installFromLock, $withDevReqs, 'force-updates', $operations);
@@ -578,10 +576,8 @@ class Installer
                     && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
                     && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
                 ) {
-                    if ($this->io->isDebug()) {
-                        $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version');
-                        $this->io->writeError('');
-                    }
+                    $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
+                    $this->io->writeError('', true, IOInterface::DEBUG);
 
                     continue;
                 }

+ 1 - 3
src/Composer/Installer/PearInstaller.php

@@ -75,9 +75,7 @@ class PearInstaller extends LibraryInstaller
         $pearExtractor = new PearPackageExtractor($packageArchive);
         $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
 
-        if ($this->io->isVerbose()) {
-            $this->io->writeError('    Cleaning up');
-        }
+        $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
         $this->filesystem->unlink($packageArchive);
     }
 

+ 1 - 3
src/Composer/Plugin/PluginManager.php

@@ -206,9 +206,7 @@ class PluginManager
      */
     private function addPlugin(PluginInterface $plugin)
     {
-        if ($this->io->isDebug()) {
-            $this->io->writeError('Loading plugin '.get_class($plugin));
-        }
+        $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
         $this->plugins[] =  $plugin;
         $plugin->activate($this->composer, $this->io);
 

+ 3 - 7
src/Composer/Repository/ArtifactRepository.php

@@ -67,16 +67,12 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
 
             $package = $this->getComposerInformation($file);
             if (!$package) {
-                if ($io->isVerbose()) {
-                    $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package");
-                }
+                $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
                 continue;
             }
 
-            if ($io->isVerbose()) {
-                $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
-                $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()));
-            }
+            $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
+            $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
 
             $this->addPackage($package);
         }

+ 1 - 3
src/Composer/Repository/PearRepository.php

@@ -105,9 +105,7 @@ class PearRepository extends ArrayRepository implements ConfigurableRepositoryIn
                 try {
                     $normalizedVersion = $versionParser->normalize($version);
                 } catch (\UnexpectedValueException $e) {
-                    if ($this->io->isVerbose()) {
-                        $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage());
-                    }
+                    $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
                     continue;
                 }
 

+ 1 - 3
src/Composer/Repository/Vcs/GitBitbucketDriver.php

@@ -160,9 +160,7 @@ class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface
         }
 
         if (!extension_loaded('openssl')) {
-            if ($io->isVerbose()) {
-                $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.');
-            }
+            $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
 
             return false;
         }

+ 1 - 3
src/Composer/Repository/Vcs/GitHubDriver.php

@@ -268,9 +268,7 @@ class GitHubDriver extends VcsDriver
         }
 
         if (!extension_loaded('openssl')) {
-            if ($io->isVerbose()) {
-                $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.');
-            }
+            $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
 
             return false;
         }

+ 1 - 3
src/Composer/Repository/Vcs/GitLabDriver.php

@@ -367,9 +367,7 @@ class GitLabDriver extends VcsDriver
         }
 
         if ('https' === $scheme && !extension_loaded('openssl')) {
-            if ($io->isVerbose()) {
-                $io->write('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.');
-            }
+            $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
 
             return false;
         }

+ 1 - 3
src/Composer/Repository/Vcs/HgBitbucketDriver.php

@@ -170,9 +170,7 @@ class HgBitbucketDriver extends VcsDriver
         }
 
         if (!extension_loaded('openssl')) {
-            if ($io->isVerbose()) {
-                $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.');
-            }
+            $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
 
             return false;
         }

+ 8 - 16
src/Composer/Util/RemoteFilesystem.php

@@ -227,9 +227,7 @@ class RemoteFilesystem
         unset($tempAdditionalOptions);
         $userlandFollow = isset($options['http']['follow_location']) && !$options['http']['follow_location'];
 
-        if ($this->io->isDebug()) {
-            $this->io->writeError((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl);
-        }
+        $this->io->writeError((substr($fileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $fileUrl, true, IOInterface::DEBUG);
 
         if (isset($options['github-token'])) {
             $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
@@ -609,13 +607,11 @@ class RemoteFilesystem
                 // Handle subjectAltName on lesser PHP's.
                 $certMap = $this->peerCertificateMap[$urlAuthority];
 
-                if ($this->io->isDebug()) {
-                    $this->io->writeError(sprintf(
-                        'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
-                        $certMap['cn'],
-                        $urlAuthority
-                    ));
-                }
+                $this->io->writeError(sprintf(
+                    'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
+                    $certMap['cn'],
+                    $urlAuthority
+                ), true, IOInterface::DEBUG);
 
                 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
                 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
@@ -689,9 +685,7 @@ class RemoteFilesystem
         if (!empty($targetUrl)) {
             $this->redirects++;
 
-            if ($this->io->isDebug()) {
-                $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl));
-            }
+            $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
 
             $additionalOptions['redirects'] = $this->redirects;
 
@@ -914,9 +908,7 @@ class RemoteFilesystem
             return $files[$filename];
         }
 
-        if ($this->io->isDebug()) {
-            $this->io->writeError('Checking CA file '.realpath($filename));
-        }
+        $this->io->writeError('Checking CA file '.realpath($filename), true, IOInterface::DEBUG);
         $contents = file_get_contents($filename);
 
         // assume the CA is valid if php is vulnerable to

+ 9 - 0
tests/Composer/Test/ApplicationTest.php

@@ -14,6 +14,7 @@ namespace Composer\Test;
 
 use Composer\Console\Application;
 use Composer\TestCase;
+use Symfony\Component\Console\Output\OutputInterface;
 
 class ApplicationTest extends TestCase
 {
@@ -30,11 +31,19 @@ class ApplicationTest extends TestCase
 
         $index = 0;
         if (extension_loaded('xdebug')) {
+            $outputMock->expects($this->at($index++))
+                ->method("getVerbosity")
+                ->willReturn(OutputInterface::VERBOSITY_NORMAL);
+
             $outputMock->expects($this->at($index++))
                 ->method("write")
                 ->with($this->equalTo('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>'));
         }
 
+        $outputMock->expects($this->at($index++))
+            ->method("getVerbosity")
+            ->willReturn(OutputInterface::VERBOSITY_NORMAL);
+
         $outputMock->expects($this->at($index++))
             ->method("write")
             ->with($this->equalTo(sprintf('<warning>Warning: This development build of composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.</warning>', $_SERVER['PHP_SELF'])));

+ 15 - 42
tests/Composer/Test/EventDispatcher/EventDispatcherTest.php

@@ -15,9 +15,11 @@ namespace Composer\Test\EventDispatcher;
 use Composer\EventDispatcher\Event;
 use Composer\Installer\InstallerEvents;
 use Composer\TestCase;
+use Composer\IO\BufferIO;
 use Composer\Script\ScriptEvents;
 use Composer\Script\CommandEvent;
 use Composer\Util\ProcessExecutor;
+use Symfony\Component\Console\Output\OutputInterface;
 
 class EventDispatcherTest extends TestCase
 {
@@ -101,7 +103,7 @@ class EventDispatcherTest extends TestCase
         $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')
             ->setConstructorArgs(array(
                 $this->getMock('Composer\Composer'),
-                $io = $this->getMock('Composer\IO\IOInterface'),
+                $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
                 $process,
             ))
             ->setMethods(array(
@@ -123,23 +125,12 @@ class EventDispatcherTest extends TestCase
             ->method('getListeners')
             ->will($this->returnValue($listeners));
 
-        $io->expects($this->any())
-            ->method('isVerbose')
-            ->willReturn(1);
-
-        $io->expects($this->at(1))
-            ->method('writeError')
-            ->with($this->equalTo('> post-install-cmd: echo -n foo'));
-
-        $io->expects($this->at(3))
-            ->method('writeError')
-            ->with($this->equalTo('> post-install-cmd: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'));
-
-        $io->expects($this->at(5))
-            ->method('writeError')
-            ->with($this->equalTo('> post-install-cmd: echo -n bar'));
-
         $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false);
+
+        $expected = '> post-install-cmd: echo -n foo'.PHP_EOL.
+            '> post-install-cmd: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL.
+            '> post-install-cmd: echo -n bar'.PHP_EOL;
+        $this->assertEquals($expected, $io->getOutput());
     }
 
     public function testDispatcherCanExecuteComposerScriptGroups()
@@ -148,7 +139,7 @@ class EventDispatcherTest extends TestCase
         $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')
             ->setConstructorArgs(array(
                 $composer = $this->getMock('Composer\Composer'),
-                $io = $this->getMock('Composer\IO\IOInterface'),
+                $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
                 $process,
             ))
             ->setMethods(array(
@@ -174,31 +165,13 @@ class EventDispatcherTest extends TestCase
                 return array();
             }));
 
-        $io->expects($this->any())
-            ->method('isVerbose')
-            ->willReturn(1);
-
-        $io->expects($this->at(1))
-            ->method('writeError')
-            ->with($this->equalTo('> root: @group'));
-
-        $io->expects($this->at(3))
-            ->method('writeError')
-            ->with($this->equalTo('> group: echo -n foo'));
-
-        $io->expects($this->at(5))
-            ->method('writeError')
-            ->with($this->equalTo('> group: @subgroup'));
-
-        $io->expects($this->at(7))
-            ->method('writeError')
-            ->with($this->equalTo('> subgroup: echo -n baz'));
-
-        $io->expects($this->at(9))
-            ->method('writeError')
-            ->with($this->equalTo('> group: echo -n bar'));
-
         $dispatcher->dispatch('root', new CommandEvent('root', $composer, $io));
+        $expected = '> root: @group'.PHP_EOL.
+            '> group: echo -n foo'.PHP_EOL.
+            '> group: @subgroup'.PHP_EOL.
+            '> subgroup: echo -n baz'.PHP_EOL.
+            '> group: echo -n bar'.PHP_EOL;
+        $this->assertEquals($expected, $io->getOutput());
     }
 
     /**

+ 4 - 4
tests/Composer/Test/Fixtures/installer/abandoned-listed.test

@@ -24,12 +24,12 @@ Abandoned packages are flagged
 --RUN--
 install
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies (including require-dev)</info>
+Loading composer repositories with package information
+Installing dependencies (including require-dev)
 <warning>Package a/a is abandoned, you should avoid using it. No replacement was suggested.</warning>
 <warning>Package c/c is abandoned, you should avoid using it. Use b/b instead.</warning>
-<info>Writing lock file</info>
-<info>Generating autoload files</info>
+Writing lock file
+Generating autoload files
 
 --EXPECT--
 Installing a/a (1.0.0)

+ 3 - 3
tests/Composer/Test/Fixtures/installer/broken-deps-do-not-replace.test

@@ -21,9 +21,9 @@ Broken dependencies should not lead to a replacer being installed which is not m
 --RUN--
 install
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies (including require-dev)</info>
-<error>Your requirements could not be resolved to an installable set of packages.</error>
+Loading composer repositories with package information
+Installing dependencies (including require-dev)
+Your requirements could not be resolved to an installable set of packages.
 
   Problem 1
     - c/c 1.0.0 requires x/x 1.0 -> no matching package found.

+ 4 - 4
tests/Composer/Test/Fixtures/installer/suggest-installed.test

@@ -19,10 +19,10 @@ Suggestions are not displayed for installed packages
 --RUN--
 install
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies (including require-dev)</info>
-<info>Writing lock file</info>
-<info>Generating autoload files</info>
+Loading composer repositories with package information
+Installing dependencies (including require-dev)
+Writing lock file
+Generating autoload files
 
 --EXPECT--
 Installing a/a (1.0.0)

+ 4 - 4
tests/Composer/Test/Fixtures/installer/suggest-prod.test

@@ -17,10 +17,10 @@ Suggestions are not displayed in non-dev mode
 --RUN--
 install --no-dev
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies</info>
-<info>Writing lock file</info>
-<info>Generating autoload files</info>
+Loading composer repositories with package information
+Installing dependencies
+Writing lock file
+Generating autoload files
 
 --EXPECT--
 Installing a/a (1.0.0)

+ 4 - 4
tests/Composer/Test/Fixtures/installer/suggest-replaced.test

@@ -19,10 +19,10 @@ Suggestions are not displayed for packages if they are replaced
 --RUN--
 install
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies (including require-dev)</info>
-<info>Writing lock file</info>
-<info>Generating autoload files</info>
+Loading composer repositories with package information
+Installing dependencies (including require-dev)
+Writing lock file
+Generating autoload files
 
 --EXPECT--
 Installing c/c (1.0.0)

+ 4 - 4
tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test

@@ -17,11 +17,11 @@ Suggestions are displayed
 --RUN--
 install
 --EXPECT-OUTPUT--
-<info>Loading composer repositories with package information</info>
-<info>Installing dependencies (including require-dev)</info>
+Loading composer repositories with package information
+Installing dependencies (including require-dev)
 a/a suggests installing b/b (an obscure reason)
-<info>Writing lock file</info>
-<info>Generating autoload files</info>
+Writing lock file
+Generating autoload files
 
 --EXPECT--
 Installing a/a (1.0.0)

+ 20 - 7
tests/Composer/Test/IO/ConsoleIOTest.php

@@ -14,6 +14,7 @@ namespace Composer\Test\IO;
 
 use Composer\IO\ConsoleIO;
 use Composer\TestCase;
+use Symfony\Component\Console\Output\OutputInterface;
 
 class ConsoleIOTest extends TestCase
 {
@@ -40,6 +41,9 @@ class ConsoleIOTest extends TestCase
     {
         $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface');
         $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+        $outputMock->expects($this->once())
+            ->method('getVerbosity')
+            ->willReturn(OutputInterface::VERBOSITY_NORMAL);
         $outputMock->expects($this->once())
             ->method('write')
             ->with($this->equalTo('some information about something'), $this->equalTo(false));
@@ -53,6 +57,9 @@ class ConsoleIOTest extends TestCase
     {
         $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface');
         $outputMock = $this->getMock('Symfony\Component\Console\Output\ConsoleOutputInterface');
+        $outputMock->expects($this->once())
+            ->method('getVerbosity')
+            ->willReturn(OutputInterface::VERBOSITY_NORMAL);
         $outputMock->expects($this->once())
             ->method('getErrorOutput')
             ->willReturn($outputMock);
@@ -69,6 +76,9 @@ class ConsoleIOTest extends TestCase
     {
         $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface');
         $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+        $outputMock->expects($this->once())
+            ->method('getVerbosity')
+            ->willReturn(OutputInterface::VERBOSITY_NORMAL);
         $outputMock->expects($this->once())
             ->method('write')
             ->with(
@@ -95,25 +105,28 @@ class ConsoleIOTest extends TestCase
         $inputMock = $this->getMock('Symfony\Component\Console\Input\InputInterface');
         $outputMock = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
 
-        $outputMock->expects($this->at(0))
+        $outputMock->expects($this->any())
+            ->method('getVerbosity')
+            ->willReturn(OutputInterface::VERBOSITY_NORMAL);
+        $outputMock->expects($this->at(1))
             ->method('write')
             ->with($this->equalTo('something (<question>strlen = 23</question>)'));
-        $outputMock->expects($this->at(1))
+        $outputMock->expects($this->at(3))
             ->method('write')
             ->with($this->equalTo(str_repeat("\x08", 23)), $this->equalTo(false));
-        $outputMock->expects($this->at(2))
+        $outputMock->expects($this->at(5))
             ->method('write')
             ->with($this->equalTo('shorter (<comment>12</comment>)'), $this->equalTo(false));
-        $outputMock->expects($this->at(3))
+        $outputMock->expects($this->at(7))
             ->method('write')
             ->with($this->equalTo(str_repeat(' ', 11)), $this->equalTo(false));
-        $outputMock->expects($this->at(4))
+        $outputMock->expects($this->at(9))
             ->method('write')
             ->with($this->equalTo(str_repeat("\x08", 11)), $this->equalTo(false));
-        $outputMock->expects($this->at(5))
+        $outputMock->expects($this->at(11))
             ->method('write')
             ->with($this->equalTo(str_repeat("\x08", 12)), $this->equalTo(false));
-        $outputMock->expects($this->at(6))
+        $outputMock->expects($this->at(13))
             ->method('write')
             ->with($this->equalTo('something longer than initial (<info>34</info>)'));
 

+ 5 - 12
tests/Composer/Test/InstallerTest.php

@@ -26,7 +26,10 @@ use Composer\Test\Mock\InstalledFilesystemRepositoryMock;
 use Composer\Test\Mock\InstallationManagerMock;
 use Symfony\Component\Console\Input\StringInput;
 use Symfony\Component\Console\Output\StreamOutput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Formatter\OutputFormatter;
 use Composer\TestCase;
+use Composer\IO\BufferIO;
 
 class InstallerTest extends TestCase
 {
@@ -146,18 +149,7 @@ class InstallerTest extends TestCase
             }
         }
 
-        $output = null;
-        $io = $this->getMock('Composer\IO\IOInterface');
-        $callback = function ($text, $newline) use (&$output) {
-            $output .= $text . ($newline ? "\n" : "");
-        };
-        $io->expects($this->any())
-            ->method('write')
-            ->will($this->returnCallback($callback));
-        $io->expects($this->any())
-            ->method('writeError')
-            ->will($this->returnCallback($callback));
-
+        $io = new BufferIO('', OutputInterface::VERBOSITY_NORMAL, new OutputFormatter(false));
         $composer = FactoryMock::create($io, $composerConfig);
 
         $jsonMock = $this->getMockBuilder('Composer\Json\JsonFile')->disableOriginalConstructor()->getMock();
@@ -233,6 +225,7 @@ class InstallerTest extends TestCase
         $appOutput = fopen('php://memory', 'w+');
         $result = $application->run(new StringInput($run), new StreamOutput($appOutput));
         fseek($appOutput, 0);
+        $output = str_replace("\r", '', $io->getOutput());
         $this->assertEquals($expectExitCode, $result, $output . stream_get_contents($appOutput));
 
         if ($expectLock) {