From 44634a689d7342c4814885af888955e4f507bcab Mon Sep 17 00:00:00 2001 From: Rafael Kassner Date: Mon, 3 Oct 2016 13:17:07 +0200 Subject: [PATCH 1/9] HgDriver does not identify bitbucket mercurial repos correctly --- src/Composer/Repository/Vcs/HgDriver.php | 2 +- .../Test/Repository/Vcs/HgDriverTest.php | 63 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/Composer/Test/Repository/Vcs/HgDriverTest.php diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index c82c8c4aa..4dc103d38 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -195,7 +195,7 @@ class HgDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { + if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { return true; } diff --git a/tests/Composer/Test/Repository/Vcs/HgDriverTest.php b/tests/Composer/Test/Repository/Vcs/HgDriverTest.php new file mode 100644 index 000000000..3b62ac317 --- /dev/null +++ b/tests/Composer/Test/Repository/Vcs/HgDriverTest.php @@ -0,0 +1,63 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Repository\Vcs; + +use Composer\Repository\Vcs\HgDriver; +use Composer\TestCase; +use Composer\Util\Filesystem; +use Composer\Config; + +class HgDriverTest extends TestCase +{ + + /** @type \Composer\IO\IOInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $io; + /** @type \Composer\Config */ + private $config; + /** @type string */ + private $home; + + public function setUp() + { + $this->io = $this->getMock('Composer\IO\IOInterface'); + $this->home = $this->getUniqueTmpDirectory(); + $this->config = new Config(); + $this->config->merge(array( + 'config' => array( + 'home' => $this->home, + ), + )); + } + + public function tearDown() + { + $fs = new Filesystem; + $fs->removeDirectory($this->home); + } + + public function testSupports() + { + $this->assertTrue( + HgDriver::supports($this->io, $this->config, 'ssh://bitbucket.org/user/repo') + ); + + $this->assertTrue( + HgDriver::supports($this->io, $this->config, 'ssh://hg@bitbucket.org/user/repo') + ); + + $this->assertTrue( + HgDriver::supports($this->io, $this->config, 'ssh://user@bitbucket.org/user/repo') + ); + } + +} From 34ec5fba58487770e2118653d0153d9f3e17fe98 Mon Sep 17 00:00:00 2001 From: Rafael Kassner Date: Mon, 3 Oct 2016 13:35:48 +0200 Subject: [PATCH 2/9] Code review fixes --- .../Test/Repository/Vcs/HgDriverTest.php | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/Composer/Test/Repository/Vcs/HgDriverTest.php b/tests/Composer/Test/Repository/Vcs/HgDriverTest.php index 3b62ac317..da326aaf5 100644 --- a/tests/Composer/Test/Repository/Vcs/HgDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/HgDriverTest.php @@ -22,7 +22,7 @@ class HgDriverTest extends TestCase /** @type \Composer\IO\IOInterface|\PHPUnit_Framework_MockObject_MockObject */ private $io; - /** @type \Composer\Config */ + /** @type Config */ private $config; /** @type string */ private $home; @@ -45,18 +45,24 @@ class HgDriverTest extends TestCase $fs->removeDirectory($this->home); } - public function testSupports() + /** + * @dataProvider supportsDataProvider + */ + public function testSupports($repositoryUrl) { $this->assertTrue( - HgDriver::supports($this->io, $this->config, 'ssh://bitbucket.org/user/repo') + HgDriver::supports($this->io, $this->config, $repositoryUrl) ); + } - $this->assertTrue( - HgDriver::supports($this->io, $this->config, 'ssh://hg@bitbucket.org/user/repo') - ); - - $this->assertTrue( - HgDriver::supports($this->io, $this->config, 'ssh://user@bitbucket.org/user/repo') + public function supportsDataProvider() + { + return array( + array('ssh://bitbucket.org/user/repo'), + array('ssh://hg@bitbucket.org/user/repo'), + array('ssh://user@bitbucket.org/user/repo'), + array('https://bitbucket.org/user/repo'), + array('https://user@bitbucket.org/user/repo'), ); } From ce6a3c0dd7ff245bf3b2694c2325cebbdaaccd5b Mon Sep 17 00:00:00 2001 From: Andrew Taylor Date: Mon, 17 Oct 2016 20:29:52 +0100 Subject: [PATCH 3/9] Issue 5769 dev mode varaible --- doc/articles/scripts.md | 2 ++ src/Composer/Installer.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index f394f28e9..9b350c614 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -150,6 +150,8 @@ class MyClass } ``` +**Note:** During composer install / update, a `COMPOSER_DEV_MODE` php environment variable is set. If composer install / update was run with the `--no-dev option`, this variable will be set to 0, otherwise it will be set to 1. This exposes the mode in which the install / update was run, to any post-install / update commands. + ## Event classes When an event is fired, your PHP callback receives as first argument a diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 49e82f06c..b1ac40834 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -292,6 +292,9 @@ class Installer } if ($this->runScripts) { + $devMode = (int) $this->devMode; + putenv("COMPOSER_DEV_MODE=$devMode"); + // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); From 235b1cca81f959fcaebd52222e1ec8e7268b9698 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 19 Oct 2016 08:40:06 +0200 Subject: [PATCH 4/9] wordwrap and minor rephrasing --- doc/articles/scripts.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 9b350c614..66d84b8c2 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -22,15 +22,19 @@ Composer fires the following named events during its execution process: ### Command Events -- **pre-install-cmd**: occurs before the `install` command is executed with a lock file present. -- **post-install-cmd**: occurs after the `install` command has been executed with a lock file present. -- **pre-update-cmd**: occurs before the `update` command is executed, or before the `install` command is executed without a lock file present. -- **post-update-cmd**: occurs after the `update` command has been executed, or after the `install` command has been executed without a lock file present. +- **pre-install-cmd**: occurs before the `install` command is executed with a + lock file present. +- **post-install-cmd**: occurs after the `install` command has been executed + with a lock file present. +- **pre-update-cmd**: occurs before the `update` command is executed, or before + the `install` command is executed without a lock file present. +- **post-update-cmd**: occurs after the `update` command has been executed, or + after the `install` command has been executed without a lock file present. - **post-status-cmd**: occurs after the `status` command has been executed. - **pre-archive-cmd**: occurs before the `archive` command is executed. - **post-archive-cmd**: occurs after the `archive` command has been executed. -- **pre-autoload-dump**: occurs before the autoloader is dumped, either - during `install`/`update`, or via the `dump-autoload` command. +- **pre-autoload-dump**: occurs before the autoloader is dumped, either during + `install`/`update`, or via the `dump-autoload` command. - **post-autoload-dump**: occurs after the autoloader has been dumped, either during `install`/`update`, or via the `dump-autoload` command. - **post-root-package-install**: occurs after the root package has been @@ -150,7 +154,10 @@ class MyClass } ``` -**Note:** During composer install / update, a `COMPOSER_DEV_MODE` php environment variable is set. If composer install / update was run with the `--no-dev option`, this variable will be set to 0, otherwise it will be set to 1. This exposes the mode in which the install / update was run, to any post-install / update commands. +**Note:** During a composer install or update process, a variable named +`COMPOSER_DEV_MODE` will be added to the environment. If the command was run +with the `--no-dev` flag, this variable will be set to 0, otherwise it will be +set to 1. ## Event classes From 57ec0d1815e6723174f03a6ebdc5d6fa50e766a1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 29 Oct 2016 08:03:08 -0700 Subject: [PATCH 5/9] added more information in the output --- src/Composer/Installer.php | 32 +++++++++++++++++++ .../Fixtures/installer/abandoned-listed.test | 1 + .../installer/github-issues-4795-2.test | 1 + .../Fixtures/installer/suggest-installed.test | 1 + .../Test/Fixtures/installer/suggest-prod.test | 1 + .../Fixtures/installer/suggest-replaced.test | 1 + .../installer/suggest-uninstalled.test | 1 + 7 files changed, 38 insertions(+) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 49e82f06c..5a4aee95c 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -492,6 +492,38 @@ class Installer $devPackages = null; } + if ($operations) { + $installs = $updates = $uninstalls = array(); + foreach ($operations as $operation) { + if ($operation instanceof InstallOperation) { + $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion(); + } elseif ($operation instanceof UpdateOperation) { + $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion(); + } elseif ($operation instanceof UninstallOperation) { + $uninstalls[] = $operation->getPackage()->getPrettyName(); + } + } + + $this->io->writeError( + sprintf("Package operations: %d install%s, %d update%s, %d removal%s", + count($installs), + 1 === count($installs) ? '' : 's', + count($updates), + 1 === count($updates) ? '' : 's', + count($uninstalls), + 1 === count($uninstalls) ? '' : 's') + ); + if ($installs) { + $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE); + } + if ($updates) { + $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE); + } + if ($uninstalls) { + $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE); + } + } + foreach ($operations as $operation) { // collect suggestions if ('install' === $operation->getJobType()) { diff --git a/tests/Composer/Test/Fixtures/installer/abandoned-listed.test b/tests/Composer/Test/Fixtures/installer/abandoned-listed.test index bc8a0cdb6..7eba0a6f0 100644 --- a/tests/Composer/Test/Fixtures/installer/abandoned-listed.test +++ b/tests/Composer/Test/Fixtures/installer/abandoned-listed.test @@ -26,6 +26,7 @@ install --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies (including require-dev) +Package operations: 2 installs, 0 updates, 0 removals Package a/a is abandoned, you should avoid using it. No replacement was suggested. Package c/c is abandoned, you should avoid using it. Use b/b instead. Writing lock file diff --git a/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test b/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test index 29fc0d38f..d807c6df8 100644 --- a/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test +++ b/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test @@ -36,6 +36,7 @@ update a b --with-dependencies --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies (including require-dev) +Package operations: 0 installs, 2 updates, 0 removals Writing lock file Generating autoload files diff --git a/tests/Composer/Test/Fixtures/installer/suggest-installed.test b/tests/Composer/Test/Fixtures/installer/suggest-installed.test index df573c997..198203ce9 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-installed.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-installed.test @@ -21,6 +21,7 @@ install --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies (including require-dev) +Package operations: 2 installs, 0 updates, 0 removals Writing lock file Generating autoload files diff --git a/tests/Composer/Test/Fixtures/installer/suggest-prod.test b/tests/Composer/Test/Fixtures/installer/suggest-prod.test index 0fe9c8853..40546f8d0 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-prod.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-prod.test @@ -19,6 +19,7 @@ install --no-dev --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies +Package operations: 1 install, 0 updates, 0 removals Writing lock file Generating autoload files diff --git a/tests/Composer/Test/Fixtures/installer/suggest-replaced.test b/tests/Composer/Test/Fixtures/installer/suggest-replaced.test index 38755d7fb..f18054d74 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-replaced.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-replaced.test @@ -21,6 +21,7 @@ install --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies (including require-dev) +Package operations: 2 installs, 0 updates, 0 removals Writing lock file Generating autoload files diff --git a/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test b/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test index fda020699..ae5ff36e3 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test @@ -19,6 +19,7 @@ install --EXPECT-OUTPUT-- Loading composer repositories with package information Updating dependencies (including require-dev) +Package operations: 1 install, 0 updates, 0 removals a/a suggests installing b/b (an obscure reason) Writing lock file Generating autoload files From 1882f9a502ab505806358b63615f7e77f51fd913 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 3 Nov 2016 13:19:20 +0100 Subject: [PATCH 6/9] Enhance the json schema with validation for map objects --- res/composer-schema.json | 79 +++++++++++++++---- .../Composer/Test/Json/ComposerSchemaTest.php | 8 ++ 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/res/composer-schema.json b/res/composer-schema.json index 22e527428..10058a347 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -77,32 +77,44 @@ "require": { "type": "object", "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "replace": { "type": "object", "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "conflict": { "type": "object", "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "provide": { "type": "object", "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "require-dev": { "type": "object", "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "suggest": { "type": "object", "description": "This is a hash of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "config": { "type": "object", @@ -134,12 +146,16 @@ "github-oauth": { "type": "object", "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"\"}.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "gitlab-oauth": { "type": "object", "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"\"}.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "disable-tls": { "type": "boolean", @@ -160,7 +176,20 @@ "http-basic": { "type": "object", "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.", - "additionalProperties": true + "additionalProperties": { + "type": "object", + "required": ["username", "password"], + "properties": { + "username": { + "type": "string", + "description": "The username used for HTTP Basic authentication" + }, + "password": { + "type": "string", + "description": "The password used for HTTP Basic authentication" + } + } + } }, "store-auths": { "type": ["string", "boolean"], @@ -169,7 +198,9 @@ "platform": { "type": "object", "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.", - "additionalProperties": true + "additionalProperties": { + "type": "string" + } }, "vendor-dir": { "type": "string", @@ -275,12 +306,22 @@ "psr-0": { "type": "object", "description": "This is a hash of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.", - "additionalProperties": true + "additionalProperties": { + "type": ["string", "array"], + "items": { + "type": "string" + } + } }, "psr-4": { "type": "object", "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", - "additionalProperties": true + "additionalProperties": { + "type": ["string", "array"], + "items": { + "type": "string" + } + } }, "classmap": { "type": "array", @@ -303,12 +344,22 @@ "psr-0": { "type": "object", "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.", - "additionalProperties": true + "additionalProperties": { + "type": ["string", "array"], + "items": { + "type": "string" + } + } }, "psr-4": { "type": "object", "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", - "additionalProperties": true + "additionalProperties": { + "type": ["string", "array"], + "items": { + "type": "string" + } + } }, "classmap": { "type": "array", diff --git a/tests/Composer/Test/Json/ComposerSchemaTest.php b/tests/Composer/Test/Json/ComposerSchemaTest.php index b58eebccc..d4f63513a 100644 --- a/tests/Composer/Test/Json/ComposerSchemaTest.php +++ b/tests/Composer/Test/Json/ComposerSchemaTest.php @@ -44,6 +44,14 @@ class ComposerSchemaTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->check($json)); } + public function testRequireTypes() + { + $json = '{"name": "name", "description": "description", "require": {"a": ["b"]} }'; + $this->assertEquals(array( + array('property' => 'require.a', 'message' => 'Array value found, but a string is required', 'constraint' => 'type'), + ), $this->check($json)); + } + public function testMinimumStabilityValues() { $json = '{ "name": "vendor/package", "description": "generic description", "minimum-stability": "" }'; From d0918b05944cdbaeaee3abb0e3cfeaf415a7e0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Fri, 4 Nov 2016 23:25:21 +0100 Subject: [PATCH 7/9] Make download shell script PSR-2 compatible Avoid `else` --- .../how-to-install-composer-programmatically.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/faqs/how-to-install-composer-programmatically.md b/doc/faqs/how-to-install-composer-programmatically.md index ec252825d..4369ec9ce 100644 --- a/doc/faqs/how-to-install-composer-programmatically.md +++ b/doc/faqs/how-to-install-composer-programmatically.md @@ -9,21 +9,21 @@ An alternative is to use this script which only works with unix utils: ```bash #!/bin/sh -EXPECTED_SIGNATURE=$(wget https://composer.github.io/installer.sig -O - -q) +EXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig) php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');") -if [ "$EXPECTED_SIGNATURE" = "$ACTUAL_SIGNATURE" ] +if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] then - php composer-setup.php --quiet - RESULT=$? - rm composer-setup.php - exit $RESULT -else >&2 echo 'ERROR: Invalid installer signature' rm composer-setup.php exit 1 fi + +php composer-setup.php --quiet +RESULT=$? +rm composer-setup.php +exit $RESULT ``` The script will exit with 1 in case of failure, or 0 on success, and is quiet From 103624d4ed7da1719f8204f11f97147108e1e975 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 5 Nov 2016 21:18:18 -0700 Subject: [PATCH 8/9] Remove usage of echo when executing Composer script --- src/Composer/Util/ProcessExecutor.php | 12 +++++++++++- .../Test/EventDispatcher/EventDispatcherTest.php | 8 +++++--- tests/Composer/Test/Util/ProcessExecutorTest.php | 11 +++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index ec1b9a3db..506d3e966 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -99,7 +99,17 @@ class ProcessExecutor return; } - echo $buffer; + if (null === $this->io) { + echo $buffer; + + return; + } + + if (Process::ERR === $type) { + $this->io->writeError($buffer); + } else { + $this->io->write($buffer); + } } public static function getTimeout() diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 468c5d0e9..114d14b8b 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -340,7 +340,7 @@ class EventDispatcherTest extends TestCase ->setConstructorArgs(array( $this->createComposerInstance(), $io = $this->getMock('Composer\IO\IOInterface'), - new ProcessExecutor, + new ProcessExecutor($io), )) ->setMethods(array('getListeners')) ->getMock(); @@ -354,9 +354,11 @@ class EventDispatcherTest extends TestCase ->method('writeError') ->with($this->equalTo('> echo foo')); - ob_start(); + $io->expects($this->once()) + ->method('write') + ->with($this->equalTo('foo'.PHP_EOL)); + $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); - $this->assertEquals('foo', trim(ob_get_clean())); } public function testDispatcherOutputsErrorOnFailedCommand() diff --git a/tests/Composer/Test/Util/ProcessExecutorTest.php b/tests/Composer/Test/Util/ProcessExecutorTest.php index 101b0b710..ba114eae5 100644 --- a/tests/Composer/Test/Util/ProcessExecutorTest.php +++ b/tests/Composer/Test/Util/ProcessExecutorTest.php @@ -35,6 +35,17 @@ class ProcessExecutorTest extends TestCase $this->assertEquals("foo".PHP_EOL, $output); } + public function testUseIOIsNotNullAndIfNotCaptured() + { + $io = $this->getMock('Composer\IO\IOInterface'); + $io->expects($this->once()) + ->method('write') + ->with($this->equalTo('foo'.PHP_EOL)); + + $process = new ProcessExecutor($io); + $process->execute('echo foo'); + } + public function testExecuteCapturesStderr() { $process = new ProcessExecutor; From f3af3da16f72731f7f4b5ef78a0862b4877bdbdf Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 6 Nov 2016 18:16:45 +0100 Subject: [PATCH 9/9] Add more comments in ConsoleIO, closes #5836 --- src/Composer/IO/ConsoleIO.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/IO/ConsoleIO.php b/src/Composer/IO/ConsoleIO.php index 7cd6fd71a..0fd93152e 100644 --- a/src/Composer/IO/ConsoleIO.php +++ b/src/Composer/IO/ConsoleIO.php @@ -206,6 +206,9 @@ class ConsoleIO extends BaseIO // write the new message $this->doWrite($messages, false, $stderr, $verbosity); + // In cmd.exe on Win8.1 (possibly 10?), the line can not be cleared, so we need to + // track the length of previous output and fill it with spaces to make sure the line is cleared. + // See https://github.com/composer/composer/pull/5836 for more details $fill = $size - strlen(strip_tags($messages)); if ($fill > 0) { // whitespace whatever has left