diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index c623ada42..45288825d 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -145,27 +145,15 @@ class EventDispatcher */ protected function doDispatch(Event $event) { - $pathStr = 'PATH'; - if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) { - $pathStr = 'Path'; - } - - // add the bin dir to the PATH to make local binaries of deps usable in scripts - $binDir = $this->composer->getConfig()->get('bin-dir'); - if (is_dir($binDir)) { - $binDir = realpath($binDir); - if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) { - $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr); - putenv($pathStr.'='.$_SERVER[$pathStr]); - } - } - $listeners = $this->getListeners($event); $this->pushEvent($event); $return = 0; foreach ($listeners as $callable) { + + $this->ensureBinDirIsInPath(); + if (!is_string($callable)) { if (!is_callable($callable)) { $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0]; @@ -545,4 +533,22 @@ class EventDispatcher { return array_pop($this->eventStack); } + + private function ensureBinDirIsInPath() + { + $pathStr = 'PATH'; + if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) { + $pathStr = 'Path'; + } + + // add the bin dir to the PATH to make local binaries of deps usable in scripts + $binDir = $this->composer->getConfig()->get('bin-dir'); + if (is_dir($binDir)) { + $binDir = realpath($binDir); + if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) { + $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr); + putenv($pathStr.'='.$_SERVER[$pathStr]); + } + } + } } diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index 3d5e0c712..04ae56c20 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -260,6 +260,60 @@ class EventDispatcherTest extends TestCase $this->assertEquals($expected, $io->getOutput()); } + public function testDispatcherAppendsDirBinOnPathForEveryListener() + { + $currentDirectoryBkp = getcwd(); + $composerBinDirBkp = getenv('COMPOSER_BIN_DIR'); + chdir(__DIR__); + putenv('COMPOSER_BIN_DIR=' . __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); + + $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->setConstructorArgs(array( + $this->createComposerInstance(), + $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE), + $process, + ))->setMethods(array( + 'getListeners', + ))->getMock(); + + $listeners = array( + 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::createsVendorBinFolderChecksEnvDoesNotContainsBin', + 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::createsVendorBinFolderChecksEnvContainsBin', + ); + + $dispatcher->expects($this->atLeastOnce())->method('getListeners')->will($this->returnValue($listeners)); + + $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); + rmdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); + rmdir(__DIR__ . sprintf('%svendor', DIRECTORY_SEPARATOR)); + + chdir($currentDirectoryBkp); + putenv('COMPOSER_BIN_DIR=' . $composerBinDirBkp); + } + + static public function createsVendorBinFolderChecksEnvDoesNotContainsBin() + { + mkdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), 0700, true); + $val = getenv('PATH'); + + if ( ! $val ) { + $val = getenv('Path'); + } + + self::assertFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + } + + static public function createsVendorBinFolderChecksEnvContainsBin() + { + $val = getenv('PATH'); + + if ( ! $val ) { + $val = getenv('Path'); + } + + self::assertNotFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); + } + static public function getTestEnv() { $val = getenv('ABC'); if ($val !== '123') {