From 44634a689d7342c4814885af888955e4f507bcab Mon Sep 17 00:00:00 2001 From: Rafael Kassner Date: Mon, 3 Oct 2016 13:17:07 +0200 Subject: [PATCH 1/4] 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/4] 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 1882f9a502ab505806358b63615f7e77f51fd913 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 3 Nov 2016 13:19:20 +0100 Subject: [PATCH 3/4] 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 103624d4ed7da1719f8204f11f97147108e1e975 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 5 Nov 2016 21:18:18 -0700 Subject: [PATCH 4/4] 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;