diff --git a/bin/composer b/bin/composer index c2b428e06..ed4979f7b 100755 --- a/bin/composer +++ b/bin/composer @@ -7,12 +7,16 @@ if (PHP_SAPI !== 'cli') { require __DIR__.'/../src/bootstrap.php'; +use Composer\Factory; use Composer\XdebugHandler; use Composer\Console\Application; error_reporting(-1); -$xdebug = new XdebugHandler(); +// Create output for XdebugHandler and Application +$output = Factory::createOutput(); + +$xdebug = new XdebugHandler($output); $xdebug->check(); unset($xdebug); @@ -46,4 +50,4 @@ if (function_exists('ini_set')) { // run the command application $application = new Application(); -$application->run(); +$application->run(null, $output); diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 430f7816c..147c29dc2 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -18,8 +18,6 @@ use Symfony\Component\Console\Application as BaseApplication; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Formatter\OutputFormatter; use Composer\Command; use Composer\Composer; use Composer\Factory; @@ -96,9 +94,7 @@ class Application extends BaseApplication public function run(InputInterface $input = null, OutputInterface $output = null) { if (null === $output) { - $styles = Factory::createAdditionalStyles(); - $formatter = new OutputFormatter(null, $styles); - $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter); + $output = Factory::createOutput(); } return parent::run($input, $output); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 4bfae989a..21ac5ac08 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -28,7 +28,9 @@ use Composer\Util\Silencer; use Composer\Plugin\PluginEvents; use Composer\EventDispatcher\Event; use Seld\JsonLint\DuplicateKeyException; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Output\ConsoleOutput; use Composer\EventDispatcher\EventDispatcher; use Composer\Autoload\AutoloadGenerator; use Composer\Package\Version\VersionParser; @@ -225,6 +227,19 @@ class Factory ); } + /** + * Creates a ConsoleOutput instance + * + * @return ConsoleOutput + */ + public static function createOutput() + { + $styles = self::createAdditionalStyles(); + $formatter = new OutputFormatter(null, $styles); + + return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter); + } + /** * @deprecated Use Composer\Repository\RepositoryFactory::defaultRepos instead */ diff --git a/src/Composer/XdebugHandler.php b/src/Composer/XdebugHandler.php index 1f9e63aa8..cdd7e68ec 100644 --- a/src/Composer/XdebugHandler.php +++ b/src/Composer/XdebugHandler.php @@ -12,6 +12,8 @@ namespace Composer; +use Symfony\Component\Console\Output\OutputInterface; + /** * @author John Stevenson */ @@ -19,6 +21,7 @@ class XdebugHandler { const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG'; + private $output; private $loaded; private $tmpIni; private $scanDir; @@ -26,8 +29,9 @@ class XdebugHandler /** * Constructor */ - public function __construct() + public function __construct(OutputInterface $output) { + $this->output = $output; $this->loaded = extension_loaded('xdebug'); $tmp = sys_get_temp_dir(); $this->tmpIni = $tmp.'/composer-php.ini'; @@ -214,6 +218,9 @@ class XdebugHandler /** * Returns the restart script arguments, adding --ansi if required * + * If we are a terminal with color support we must ensure that the --ansi + * option is set, because the restarted output is piped. + * * @param array $args The argv array * * @return array @@ -224,7 +231,7 @@ class XdebugHandler return $args; } - if ($this->isColorTerminal()) { + if ($this->output->isDecorated()) { $offset = count($args) > 1 ? 2: 1; array_splice($args, $offset, 0, '--ansi'); } @@ -232,30 +239,6 @@ class XdebugHandler return $args; } - /** - * Returns whether we are a terminal and have colour capabilities - * - * @return bool - */ - private function isColorTerminal() - { - if (function_exists('posix_isatty')) { - $result = posix_isatty(STDOUT); - } else { - // See if STDOUT is a character device (S_IFCHR) - $stat = fstat(STDOUT); - $result = ($stat['mode'] & 0170000) === 0020000; - } - - if (defined('PHP_WINDOWS_VERSION_BUILD') && $result) { - $result = false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return $result; - } - /** * Escapes a string to be used as a shell argument. * diff --git a/tests/Composer/Test/Mock/XdebugHandlerMock.php b/tests/Composer/Test/Mock/XdebugHandlerMock.php index 612dd7bf9..7f07a58b4 100644 --- a/tests/Composer/Test/Mock/XdebugHandlerMock.php +++ b/tests/Composer/Test/Mock/XdebugHandlerMock.php @@ -11,17 +11,21 @@ namespace Composer\Test\Mock; +use Composer\Factory; use Composer\XdebugHandler; class XdebugHandlerMock extends XdebugHandler { public $command; public $restarted; + public $output; - public function __construct($loaded) + public function __construct($loaded = null) { - parent::__construct(); + $this->output = Factory::createOutput(); + parent::__construct($this->output); + $loaded = $loaded === null ? true: $loaded; $class = new \ReflectionClass(get_parent_class($this)); $prop = $class->getProperty('loaded'); $prop->setAccessible(true); diff --git a/tests/Composer/Test/XdebugHandlerTest.php b/tests/Composer/Test/XdebugHandlerTest.php index 860c173de..2ada703eb 100644 --- a/tests/Composer/Test/XdebugHandlerTest.php +++ b/tests/Composer/Test/XdebugHandlerTest.php @@ -12,10 +12,13 @@ namespace Composer\Test; -use Composer\Test\Mock\XdebugHandlerMock as XdebugHandler; +use Composer\Test\Mock\XdebugHandlerMock; /** * @author John Stevenson + * + * @backupGlobals disabled + * @runTestsInSeparateProcesses */ class XdebugHandlerTest extends \PHPUnit_Framework_TestCase { @@ -23,7 +26,7 @@ class XdebugHandlerTest extends \PHPUnit_Framework_TestCase { $loaded = true; - $xdebug = new XdebugHandler($loaded); + $xdebug = new XdebugHandlerMock($loaded); $xdebug->check(); $this->assertTrue($xdebug->restarted || !defined('PHP_BINARY')); } @@ -32,7 +35,7 @@ class XdebugHandlerTest extends \PHPUnit_Framework_TestCase { $loaded = false; - $xdebug = new XdebugHandler($loaded); + $xdebug = new XdebugHandlerMock($loaded); $xdebug->check(); $this->assertFalse($xdebug->restarted); } @@ -40,10 +43,31 @@ class XdebugHandlerTest extends \PHPUnit_Framework_TestCase public function testNoRestartWhenLoadedAndAllowed() { $loaded = true; - putenv(XdebugHandler::ENV_ALLOW.'=1'); + putenv(XdebugHandlerMock::ENV_ALLOW.'=1'); - $xdebug = new XdebugHandler($loaded); + $xdebug = new XdebugHandlerMock($loaded); $xdebug->check(); $this->assertFalse($xdebug->restarted); } + + public function testForceColorSupport() + { + $xdebug = new XdebugHandlerMock(); + $xdebug->output->setDecorated(true); + $xdebug->check(); + + $args = explode(' ', $xdebug->command); + $this->assertTrue(in_array('--ansi', $args) || !defined('PHP_BINARY')); + } + + public function testIgnoreColorSupportIfNoAnsi() + { + $xdebug = new XdebugHandlerMock(); + $xdebug->output->setDecorated(true); + $_SERVER['argv'][] = '--no-ansi'; + $xdebug->check(); + + $args = explode(' ', $xdebug->command); + $this->assertTrue(!in_array('--ansi', $args) || !defined('PHP_BINARY')); + } }