1
0
Fork 0

Merge branch 'master' of https://github.com/composer/composer into pull-4690

pull/4845/head
Niels Keurentjes 2016-02-02 22:51:22 +01:00
commit 1b1462317c
35 changed files with 215 additions and 264 deletions

View File

@ -12,7 +12,7 @@
* Added --strict to the `validate` command to treat any warning as an error that then returns a non-zero exit code * Added --strict to the `validate` command to treat any warning as an error that then returns a non-zero exit code
* Added a dependency on composer/semver, which is the externalized lib for all the version constraints parsing and handling * Added a dependency on composer/semver, which is the externalized lib for all the version constraints parsing and handling
* Added support for classmap autoloading to load plugin classes and script handlers * Added support for classmap autoloading to load plugin classes and script handlers
* Added `bin-compat` config option that if set to `full` will create .bat proxy for binaries even if Compoesr runs in a linux VM * Added `bin-compat` config option that if set to `full` will create .bat proxy for binaries even if Composer runs in a linux VM
* Added SPDX 2.0 support, and externalized that in a composer/spdx-licenses lib * Added SPDX 2.0 support, and externalized that in a composer/spdx-licenses lib
* Added warnings when the classmap autoloader finds duplicate classes * Added warnings when the classmap autoloader finds duplicate classes
* Added --file to the `archive` command to choose the filename * Added --file to the `archive` command to choose the filename

View File

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

View File

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

View File

@ -136,9 +136,7 @@ class Application extends BaseApplication
if ($newWorkDir = $this->getNewWorkingDir($input)) { if ($newWorkDir = $this->getNewWorkingDir($input)) {
$oldWorkingDir = getcwd(); $oldWorkingDir = getcwd();
chdir($newWorkDir); chdir($newWorkDir);
if ($io->isDebug() >= 4) { $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
$io->writeError('Changed CWD to ' . getcwd());
}
} }
// add non-standard scripts as own commands // 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 = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
|| (($df = disk_free_space($dir = sys_get_temp_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) { } catch (\Exception $e) {
@ -222,13 +220,13 @@ class Application extends BaseApplication
Silencer::restore(); Silencer::restore();
if (defined('PHP_WINDOWS_VERSION_BUILD') && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) { 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>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>'); $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')) { 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>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>'); $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
} }
} }

View File

@ -41,7 +41,7 @@ class SolverProblemsException extends \RuntimeException
} }
if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) { if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
$text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems."; $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
} }
if ($hasExtensionProblems) { if ($hasExtensionProblems) {

View File

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

View File

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

View File

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

View File

@ -190,6 +190,20 @@ class Factory
} }
$config->setAuthConfigSource(new JsonConfigSource($file, true)); $config->setAuthConfigSource(new JsonConfigSource($file, true));
// load COMPOSER_AUTH environment variable if set
if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
$authData = json_decode($composerAuthEnv, true);
if (is_null($authData)) {
throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
}
if ($io && $io->isDebug()) {
$io->writeError('Loading auth config from COMPOSER_AUTH');
}
$config->merge(array('config' => $authData));
}
return $config; return $config;
} }
@ -293,14 +307,10 @@ class Factory
$config = static::createConfig($io, $cwd); $config = static::createConfig($io, $cwd);
$config->merge($localConfig); $config->merge($localConfig);
if (isset($composerFile)) { if (isset($composerFile)) {
if ($io && $io->isDebug()) { $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
$io->writeError('Loading config file ' . $composerFile);
}
$localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json'); $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json');
if ($localAuthFile->exists()) { if ($localAuthFile->exists()) {
if ($io && $io->isDebug()) { $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
$io->writeError('Loading config file ' . $localAuthFile->getPath());
}
$config->merge(array('config' => $localAuthFile->read())); $config->merge(array('config' => $localAuthFile->read()));
$config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true)); $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
} }
@ -435,9 +445,7 @@ class Factory
try { try {
$composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), false); $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), false);
} catch (\Exception $e) { } catch (\Exception $e) {
if ($io->isDebug()) { $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
$io->writeError('Failed to initialize global composer: '.$e->getMessage());
}
} }
return $composer; return $composer;

View File

@ -60,51 +60,26 @@ abstract class BaseIO implements IOInterface
*/ */
public function loadConfiguration(Config $config) public function loadConfiguration(Config $config)
{ {
$githubOauth = $config->get('github-oauth'); $githubOauth = $config->get('github-oauth') ?: array();
$gitlabOauth = $config->get('gitlab-oauth'); $gitlabOauth = $config->get('gitlab-oauth') ?: array();
$httpBasic = $config->get('http-basic'); $httpBasic = $config->get('http-basic') ?: array();
// Use COMPOSER_AUTH environment variable if set
if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
$authData = json_decode($composerAuthEnv, true);
if (is_null($authData)) {
throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed');
}
if (isset($authData['github-oauth'])) {
$githubOauth = array_merge($githubOauth, $authData['github-oauth']);
}
if (isset($authData['gitlab-oauth'])) {
$gitlabOauth = array_merge($gitlabOauth, $authData['gitlab-oauth']);
}
if (isset($authData['http-basic'])) {
$httpBasic = array_merge($httpBasic, $authData['http-basic']);
}
}
// reload oauth token from config if available // reload oauth token from config if available
if ($githubOauth) {
foreach ($githubOauth as $domain => $token) { foreach ($githubOauth as $domain => $token) {
if (!preg_match('{^[a-z0-9]+$}', $token)) { if (!preg_match('{^[a-z0-9]+$}', $token)) {
throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"'); throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
} }
$this->setAuthentication($domain, $token, 'x-oauth-basic'); $this->setAuthentication($domain, $token, 'x-oauth-basic');
} }
}
if ($gitlabOauth) {
foreach ($gitlabOauth as $domain => $token) { foreach ($gitlabOauth as $domain => $token) {
$this->setAuthentication($domain, $token, 'oauth2'); $this->setAuthentication($domain, $token, 'oauth2');
} }
}
// reload http basic credentials from config if available // reload http basic credentials from config if available
if ($httpBasic) {
foreach ($httpBasic as $domain => $cred) { foreach ($httpBasic as $domain => $cred) {
$this->setAuthentication($domain, $cred['username'], $cred['password']); $this->setAuthentication($domain, $cred['username'], $cred['password']);
} }
}
// setup process timeout // setup process timeout
ProcessExecutor::setTimeout((int) $config->get('process-timeout')); ProcessExecutor::setTimeout((int) $config->get('process-timeout'));

View File

@ -35,7 +35,7 @@ class BufferIO extends ConsoleIO
$input = new StringInput($input); $input = new StringInput($input);
$input->setInteractive(false); $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())); parent::__construct($input, $output, new HelperSet(array()));
} }

View File

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

View File

@ -21,6 +21,12 @@ use Composer\Config;
*/ */
interface IOInterface interface IOInterface
{ {
const QUIET = 1;
const NORMAL = 2;
const VERBOSE = 4;
const VERY_VERBOSE = 8;
const DEBUG = 16;
/** /**
* Is this input means interactive? * Is this input means interactive?
* *
@ -61,16 +67,18 @@ interface IOInterface
* *
* @param string|array $messages The message as an array of lines or a single string * @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 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. * Writes a message to the error output.
* *
* @param string|array $messages The message as an array of lines or a single string * @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 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. * Overwrites a previous message to the output.
@ -78,8 +86,9 @@ interface IOInterface
* @param string|array $messages The message as an array of lines or a single string * @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 bool $newline Whether to add a newline or not
* @param int $size The size of line * @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. * Overwrites a previous message to the error output.
@ -87,8 +96,9 @@ interface IOInterface
* @param string|array $messages The message as an array of lines or a single string * @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 bool $newline Whether to add a newline or not
* @param int $size The size of line * @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. * Asks a question to the user.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ namespace Composer\Test;
use Composer\Console\Application; use Composer\Console\Application;
use Composer\TestCase; use Composer\TestCase;
use Symfony\Component\Console\Output\OutputInterface;
class ApplicationTest extends TestCase class ApplicationTest extends TestCase
{ {
@ -30,11 +31,19 @@ class ApplicationTest extends TestCase
$index = 0; $index = 0;
if (extension_loaded('xdebug')) { if (extension_loaded('xdebug')) {
$outputMock->expects($this->at($index++))
->method("getVerbosity")
->willReturn(OutputInterface::VERBOSITY_NORMAL);
$outputMock->expects($this->at($index++)) $outputMock->expects($this->at($index++))
->method("write") ->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>')); ->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++)) $outputMock->expects($this->at($index++))
->method("write") ->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']))); ->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'])));

View File

@ -709,7 +709,7 @@ class SolverTest extends TestCase
$msg .= "Potential causes:\n"; $msg .= "Potential causes:\n";
$msg .= " - A typo in the package name\n"; $msg .= " - A typo in the package name\n";
$msg .= " - The package is not available in a stable-enough version according to your minimum-stability setting\n"; $msg .= " - The package is not available in a stable-enough version according to your minimum-stability setting\n";
$msg .= " see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.\n\n"; $msg .= " see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n\n";
$msg .= "Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems."; $msg .= "Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
$this->assertEquals($msg, $e->getMessage()); $this->assertEquals($msg, $e->getMessage());
} }

View File

@ -15,9 +15,11 @@ namespace Composer\Test\EventDispatcher;
use Composer\EventDispatcher\Event; use Composer\EventDispatcher\Event;
use Composer\Installer\InstallerEvents; use Composer\Installer\InstallerEvents;
use Composer\TestCase; use Composer\TestCase;
use Composer\IO\BufferIO;
use Composer\Script\ScriptEvents; use Composer\Script\ScriptEvents;
use Composer\Script\CommandEvent; use Composer\Script\CommandEvent;
use Composer\Util\ProcessExecutor; use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Output\OutputInterface;
class EventDispatcherTest extends TestCase class EventDispatcherTest extends TestCase
{ {
@ -101,7 +103,7 @@ class EventDispatcherTest extends TestCase
$dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')
->setConstructorArgs(array( ->setConstructorArgs(array(
$this->getMock('Composer\Composer'), $this->getMock('Composer\Composer'),
$io = $this->getMock('Composer\IO\IOInterface'), $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
$process, $process,
)) ))
->setMethods(array( ->setMethods(array(
@ -123,23 +125,12 @@ class EventDispatcherTest extends TestCase
->method('getListeners') ->method('getListeners')
->will($this->returnValue($listeners)); ->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); $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() public function testDispatcherCanExecuteComposerScriptGroups()
@ -148,7 +139,7 @@ class EventDispatcherTest extends TestCase
$dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')
->setConstructorArgs(array( ->setConstructorArgs(array(
$composer = $this->getMock('Composer\Composer'), $composer = $this->getMock('Composer\Composer'),
$io = $this->getMock('Composer\IO\IOInterface'), $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
$process, $process,
)) ))
->setMethods(array( ->setMethods(array(
@ -174,31 +165,13 @@ class EventDispatcherTest extends TestCase
return array(); 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)); $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());
} }
/** /**

View File

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

View File

@ -21,9 +21,9 @@ Broken dependencies should not lead to a replacer being installed which is not m
--RUN-- --RUN--
install install
--EXPECT-OUTPUT-- --EXPECT-OUTPUT--
<info>Loading composer repositories with package information</info> Loading composer repositories with package information
<info>Installing dependencies (including require-dev)</info> Installing dependencies (including require-dev)
<error>Your requirements could not be resolved to an installable set of packages.</error> Your requirements could not be resolved to an installable set of packages.
Problem 1 Problem 1
- c/c 1.0.0 requires x/x 1.0 -> no matching package found. - c/c 1.0.0 requires x/x 1.0 -> no matching package found.
@ -33,7 +33,7 @@ install
Potential causes: Potential causes:
- A typo in the package name - A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting - The package is not available in a stable-enough version according to your minimum-stability setting
see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details. see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems. Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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