Parcourir la source

Append the bin dir on each listener iteration

The "composer install" can create the vendor/dir folders and be used as a script item on composer.json. Having another script running after it that relies on vendor/bir binaries (such as phpunit) will cause it to not find the binary. This fix addresses the issue by trying to append the path on each script iteration.
Adriano Ferreira il y a 5 ans
Parent
commit
acc040f745

+ 21 - 15
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]);
+            }
+        }
+    }
 }

+ 54 - 0
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') {