From b0b00ad1fa1abe2601774b49f0355dcbf533cf77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Deuchnord?= Date: Mon, 26 Nov 2018 12:35:41 +0100 Subject: [PATCH] Call a script recursively with extra parameters (#7720) * Added support for calling scripts recursively (fixes #7562) --- doc/articles/scripts.md | 11 +++++ .../EventDispatcher/EventDispatcher.php | 8 +++- .../EventDispatcher/EventDispatcherTest.php | 40 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/doc/articles/scripts.md b/doc/articles/scripts.md index 79ea01519..e0c27b10f 100644 --- a/doc/articles/scripts.md +++ b/doc/articles/scripts.md @@ -238,6 +238,17 @@ one by prefixing the command name with `@`: } ``` +You can also refer a script and pass it new arguments: + +```json +{ + "scripts": { + "tests": "phpunit", + "testsVerbose": "@tests -vvv" + } +} +``` + ## Calling Composer commands To call Composer commands, you can use `@composer` which will automatically diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 7f62f6890..0fb978fd4 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -176,8 +176,12 @@ class EventDispatcher $return = false === call_user_func($callable, $event) ? 1 : 0; } elseif ($this->isComposerScript($callable)) { $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE); - $scriptName = substr($callable, 1); - $args = $event->getArguments(); + + $script = explode(' ', substr($callable, 1)); + $scriptName = $script[0]; + unset($script[0]); + + $args = array_merge($script, $event->getArguments()); $flags = $event->getFlags(); if (substr($callable, 0, 10) === '@composer ') { $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9); diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 689462bbd..5e68ebcc9 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -14,6 +14,7 @@ namespace Composer\Test\EventDispatcher; use Composer\EventDispatcher\Event; use Composer\EventDispatcher\EventDispatcher; +use Composer\EventDispatcher\ScriptExecutionException; use Composer\Installer\InstallerEvents; use Composer\Config; use Composer\Composer; @@ -274,6 +275,45 @@ class EventDispatcherTest extends TestCase $this->assertEquals($expected, $io->getOutput()); } + public function testRecursionInScriptsNames() + { + $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') + ->setConstructorArgs(array( + $composer = $this->createComposerInstance(), + $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE), + $process + )) + ->setMethods(array( + 'getListeners' + )) + ->getMock(); + + $process->expects($this->exactly(1)) + ->method('execute') + ->will($this->returnValue(0)); + + $dispatcher->expects($this->atLeastOnce()) + ->method('getListeners') + ->will($this->returnCallback(function (Event $event) { + if($event->getName() === 'hello') { + return array('echo Hello'); + } + + if($event->getName() === 'helloWorld') { + return array('@hello World'); + } + + return array(); + })); + + $dispatcher->dispatch('helloWorld', new CommandEvent('helloWorld', $composer, $io)); + $expected = "> helloWorld: @hello World".PHP_EOL. + "> hello: echo Hello " .escapeshellarg('World').PHP_EOL; + + $this->assertEquals($expected, $io->getOutput()); + } + /** * @expectedException RuntimeException */